閉じる

C#の型変換を完全解説!キャスト・Convert・Parseの違いと使い方

C#は強力な型システムを持つプログラミング言語であり、変数の型を厳格に管理することでバグを未然に防ぐ設計になっています。

しかし、実際の開発では「文字列として受け取った数値を計算に使いたい」「浮動小数点数を整数に変換したい」といった、型を変換しなければならない場面が頻繁に発生します。

C#には、キャスト、Convertクラス、Parseメソッドなど、複数の型変換手法が用意されていますが、これらを適切に使い分けることは、安全でパフォーマンスの高いコードを書くために不可欠です。

本記事では、初心者から中級者までを対象に、C#における型変換の仕組みを網羅的に詳しく解説します。

型変換の基本概念:暗黙的変換と明示的変換

C#の型変換を理解する第一歩は、暗黙的型変換明示的型変換の違いを知ることです。

プログラムが自動で行ってくれる変換と、開発者が意図を明確に示す必要がある変換には、データの整合性を守るための明確なルールが存在します。

暗黙的型変換(Implicit Conversion)

暗黙的型変換とは、コンパイラが自動的に行う変換のことです。

これは主に、データの損失が発生しないことが保証されている場合に行われます。

例えば、小さい整数型(int)をより大きな範囲を扱える浮動小数点型(double)に代入する場合などが該当します。

C#
int intValue = 100;
// int型からdouble型へは自動的に変換される(データ損失がないため)
double doubleValue = intValue;

Console.WriteLine("int値: " + intValue);
Console.WriteLine("変換後のdouble値: " + doubleValue);
実行結果
int値: 100
変換後のdouble値: 100

このように、精度の高い型や範囲の広い型へ変換する際は、特別な記述を必要としません。

明示的型変換(Explicit Conversion / Casting)

一方で、大きな型から小さな型へ変換する場合や、精度の高い型から低い型へ変換する場合は、明示的型変換(キャスト)が必要です。

これを行うには、変換先の型を括弧()で囲んで記述します。

明示的変換が必要な理由は、データの切り捨てやオーバーフローが発生するリスクがあるためです。

開発者が「データが失われる可能性があることを理解した上で変換する」という意思表示をする必要があります。

C#
double pi = 3.14159;
// doubleからintへの変換は小数点以下が失われるため、キャストが必要
int intPi = (int)pi;

Console.WriteLine("元のdouble値: " + pi);
Console.WriteLine("キャスト後のint値: " + intPi);
実行結果
元のdouble値: 3.14159
キャスト後のint値: 3

キャスト演算子による変換の詳細

キャスト演算子(type)は、最も基本的かつ高速な変換方法です。

しかし、実行時にエラーが発生する可能性や、期待しない数値の変化が起こる可能性があるため、注意深い使用が求められます。

数値型同士のキャストとデータ損失

数値型同士のキャストでは、前述の通り「情報の欠落」が最大の問題となります。

浮動小数点数から整数へのキャストでは丸め処理は行われず、単に切り捨てが行われます。

また、型が扱える最大値を超えた場合の挙動(オーバーフロー)にも注意が必要です。

デフォルトの設定では、オーバーフローしても例外は発生せず、値がループしたような(ラップアラウンド)状態になります。

C#
long longValue = 3000000000; // intの最大値(約21億)を超える値
int overflowedInt = (int)longValue;

Console.WriteLine("元のlong値: " + longValue);
Console.WriteLine("オーバーフロー後のint値: " + overflowedInt);
実行結果
元のlong値: 3000000000
オーバーフロー後のint値: -1294967296

このような予期せぬ挙動を防ぐには、checkedキーワードを使用してオーバーフロー時に例外を発生させる方法があります。

参照型のキャスト(アップキャストとダウンキャスト)

クラス継承の関係にあるオブジェクト間でもキャストが利用されます。

子クラスを親クラスとして扱う「アップキャスト」は常に安全ですが、親クラスを子クラスとして扱う「ダウンキャスト」は、実際のインスタンスがその子クラスでない場合にInvalidCastExceptionを引き起こします。

ParseとTryParse:文字列からの変換

ユーザー入力やファイルから読み込んだデータは、多くの場合「文字列(string)」として存在します。

これらを数値や日付に変換する際に使用するのがParseおよびTryParseメソッドです。

Parseメソッドの使い方とリスク

Parseは、特定の型(int, double, DateTimeなど)が持つ静的メソッドで、文字列をその型に変換します。

非常にシンプルですが、変換できない文字列を渡すと例外(FormatExceptionなど)が発生してプログラムが停止するというリスクがあります。

C#
string input = "123";
int result = int.Parse(input); // 正常に動作

string invalidInput = "abc";
// int.Parse(invalidInput); // ここで例外が発生して停止する

TryParseによる安全な変換

実務で最も推奨されるのがTryParseです。

このメソッドは、変換に成功したかどうかをbool値で返し、変換後の値はout引数を通じて受け取ります。

例外をスローしないため、パフォーマンスにも優れています。

C#
string input = "456";

// 第2引数には変換結果を格納する変数をoutキーワード付きで指定
if (int.TryParse(input, out int result))
{
    Console.WriteLine("変換成功: " + result);
}
else
{
    Console.WriteLine("変換失敗: 数値として解釈できません。");
}
実行結果
変換成功: 456

TryParseは、フォームの入力チェックなどで必須となる手法です。

常に変換失敗の可能性を考慮したコードを書くことができます。

System.Convertクラスによる変換

System.Convertクラスは、様々な基本型の間での変換をサポートするユーティリティクラスです。

キャストやParseとは異なる独自の特徴を持っています。

Convertクラスの主な特徴

Convertクラスの最大の特徴は、「nullの扱い」と「丸め処理」にあります。

nullの許容

int.Parse(null)は例外を投げますが、Convert.ToInt32(null)0を返します。

四捨五入(銀行丸め)

数値変換の際、単なる切り捨てではなく、最も近い整数に丸められます。

Convertとキャストの丸め処理の違い

以下のコードで、キャストとConvertの挙動の違いを確認してみましょう。

C#
double value1 = 3.5;
double value2 = 4.5;

// キャストは切り捨て
int cast1 = (int)value1; // 3
int cast2 = (int)value2; // 4

// Convertは「最も近い偶数」へ丸める(銀行型丸め)
int conv1 = Convert.ToInt32(value1); // 4
int conv2 = Convert.ToInt32(value2); // 4

Console.WriteLine($"Cast: {cast1}, {cast2}");
Console.WriteLine($"Convert: {conv1}, {conv2}");
実行結果
Cast: 3, 4
Convert: 4, 4

Convert.ToInt32は、端数がちょうど0.5の場合、結果が偶数になる方に丸めるという「銀行型丸め」を採用しています。

一般的な四捨五入とは異なる場合があるため注意が必要です。

as演算子とis演算子:安全な参照型変換

オブジェクト指向プログラミングにおいて、型をチェックしたり安全に変換したりするためにisas演算子が活用されます。

is演算子による型判定

is演算子は、オブジェクトが特定の型であるかどうかを確認します。

C# 7.0以降では、型判定と同時に変数への代入を行う「型パターンマッチング」が利用可能になり、非常に便利になりました。

C#
object obj = "Hello World";

if (obj is string text)
{
    // objがstring型であれば、text変数として使用可能
    Console.WriteLine("文字列の長さ: " + text.Length);
}

as演算子による安全な変換

as演算子は、変換を試み、失敗した場合は例外を投げずにnullを返します。

この性質上、参照型またはnull許容型でのみ使用可能です。

C#
object obj = 123;
string text = obj as string; // objはintなので変換失敗し、nullが代入される

if (text == null)
{
    Console.WriteLine("string型への変換に失敗しました。");
}

各変換手法の比較まとめ

どの手法を使うべきか迷った際のために、特徴を表にまとめました。

手法主な用途変換失敗時の挙動特徴
キャスト ()数値型同士、継承関係例外スロー(参照型)最も高速。数値は切り捨て。
Parse文字列からの変換例外スロー書式指定が可能。
TryParse文字列からの変換falseを返す最も安全。UI入力に最適。
Convert多種多様な型変換例外スローnullを許容し、規定値を返す。
as / is参照型の変換・判定nullを返す(as)安全なダウンキャストが可能。

実践的なアドバイスとベストプラクティス

最後に、開発現場で役立つ型変換のポイントをいくつか紹介します。

パフォーマンスを意識する

大量のデータをループ内で処理する場合、例外を発生させる可能性がある手法(Parseや明示的キャスト)は避けるべきです。

例外処理(try-catch)はコストが高いため、あらかじめTryParseやis演算子でチェックする方が遥かに高速です。

制度と丸めに注意する

金融系のアプリケーションなど、計算精度が重要なシステムでは、doubleからintへの安易なキャストはバグの温床になります。

切り捨て、切り上げ、四捨五入のどれが必要なのかを明確にし、必要に応じてMath.RoundMath.FloorMath.Ceilingを明示的に使用しましょう。

カスタム型変換の実装

自作のクラスにおいても、暗黙的または明示的な型変換を定義することができます。

implicitキーワードやexplicitキーワードを使用することで、独自のクラスをあたかも基本型のように扱うことが可能になりますが、多用しすぎるとコードの可読性を損なうため、直感的に理解できる場合に限定しましょう。

まとめ

C#における型変換は、単にデータを別の型に移し替えるだけの作業ではありません。

そこには、データの整合性を守るための厳格なルールと、予期せぬエラーを防ぐための仕組みが備わっています。

基本となる暗黙的変換の安全性を理解した上で、リスクを伴うキャストには細心の注意を払い、ユーザー入力に対してはTryParseを活用して堅牢なプログラムを構築しましょう。

また、Convertクラス独自の丸めルールや、is/as演算子による安全なオブジェクト操作を習得することで、C#マスターへの道が開けます。

適切な型変換の手法を選択できることは、美しくバグの少ないコードを書くための第一歩です。

この記事で紹介した内容を参考に、日々の開発において最適な変換手法を使い分けてみてください。

変数・データ型・演算子

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!