C#: 型の変換

1. 暗黙の型変換

暗黙の型変換は、特別な構文を必要とせず、コンパイラによって自動的に行われます。これは、より狭い型からより広い型へ代入する際に発生し、データが失われることはありません。

(1) 変換ルール

▶ サンプル

CSHARP
int a = 100;
long b = a;
int c = 42;
double d = c;
float e = 3.14f;
double f = e;
int g = 99;
string h = g.ToString();
Console.WriteLine($"int→long: {b}");
Console.WriteLine($"int→double: {d}");
Console.WriteLine($"float→double: {f}");
Console.WriteLine($"int→string: {h}");
▶ 試してみよう
TEXT 📖 参照専用
int→long: 100
int→double: 42
float→double: 3.14
int→string: 99

2. 明示的な変換

明示的な型変換を行うには、キャスト構文を使用し、値の前にターゲット型を括弧で囲む必要があります。これは、より広い型からより狭い型へ代入する際に発生し、データが失われる可能性があります。

(1) 構文

CSHARP
TargetType variable = (TargetType)value;

▶ サンプル

CSHARP
double pi = 3.14;
int truncated = (int)pi;
int number = 42;
double widened = (double)number;
long big = 3000000000L;
int overflow = (int)big;
Console.WriteLine($"(int)3.14 → {truncated}");
Console.WriteLine($"(double)42 → {widened}");
Console.WriteLine($"(int)3000000000L → {overflow}");
▶ 試してみよう
TEXT 📖 参照専用
(int)3.14 → 3
(double)42 → 42
(int)3000000000L → -1294967296

警告:明示的な型変換を行うと、精度の低下やオーバーフローが発生する可能性があります。型変換を行う前には、必ずデータの範囲を確認してください。


3. クラスの変換

System.Convert クラスは、さまざまな基本型間の変換を行うための静的メソッドを提供します。これは、直接の型キャストよりも安全で、表現力に富んでいます。

(1) 一般的な手法

方法 説明
Convert.ToInt32 int に変換
Convert.ToDouble double に変換
Convert.ToString string に変換
Convert.ToBoolean bool に変換

▶ サンプル

CSHARP
string s1 = "42";
string s2 = "3.14";
string s3 = "0";
int n1 = Convert.ToInt32(s1);
double n2 = Convert.ToDouble(s2);
string n3 = Convert.ToString(n1);
bool n4 = Convert.ToBoolean(s3);
bool n5 = Convert.ToBoolean(1);
Console.WriteLine($"ToInt32: {n1}");
Console.WriteLine($"ToDouble: {n2}");
Console.WriteLine($"ToString: {n3}");
Console.WriteLine($"ToBoolean(\"0\"): {n4}");
Console.WriteLine($"ToBoolean(1): {n5}");
▶ 試してみよう
TEXT 📖 参照専用
ToInt32: 42
ToDouble: 3.14
ToString: 42
ToBoolean("0"): False
ToBoolean(1): True

ヒント:Convert.ToBoolean は文字列の場合、"True" および "False" のみを認識します。数値の場合、0 以外の値は true、0 は false となります。


4. Parse および TryParse

(1) 解析方法

Parse は、文字列を対象の型に変換し、形式が不正な場合は FormatException をスローします。

CSHARP
int a = int.Parse("42");
double b = double.Parse("3.14");
Console.WriteLine($"int.Parse: {a}");
Console.WriteLine($"double.Parse: {b}");
▶ 試してみよう
TEXT 📖 参照専用
int.Parse: 42
double.Parse: 3.14
CSHARP
try
{
    int bad = int.Parse("hello");
}
catch (FormatException ex)
{
    Console.WriteLine($"Parse failed: {ex.Message}");
}
TEXT 📖 参照専用
Parse failed: Input string was not in a correct format.

(2) TryParse メソッド

TryParse は例外を投げません。成功を示す bool を返し、解析された値を out パラメータを介して出力します。

CSHARP
if (int.TryParse("42", out int result1))
{
    Console.WriteLine($"Parse succeeded: {result1}");
}
if (!int.TryParse("abc", out int result2))
{
    Console.WriteLine($"Parse failed, result2 = {result2}");
}
▶ 試してみよう
TEXT 📖 参照専用
Parse succeeded: 42
Parse failed, result2 = 0

ヒント:ユーザーデータなど信頼性の低い入力を扱う場合は、例外処理によるパフォーマンスの低下を避けるため、TryParse を使用することをお勧めします。


5. 梱包と開梱

(1) ボクシング

ボクシングとは、値型をobject参照型に変換するプロセスです。この際、値がスタックからヒープへコピーされ、メモリの割り当てが行われます。

CSHARP
int value = 42;
object boxed = value;
Console.WriteLine($"Boxed: {boxed}, Type: {boxed.GetType()}");
▶ 試してみよう
TEXT 📖 参照専用
Boxed: 42, Type: System.Int32

(2) 開封

アンボクシングとは、object 参照を明示的に値型にキャストするプロセスです。これには明示的なキャストが必要であり、型が一致しない場合は InvalidCastException 例外がスローされます。

CSHARP
object boxed = 42;
int unboxed = (int)boxed;
Console.WriteLine($"Unboxed: {unboxed}");
▶ 試してみよう
TEXT 📖 参照専用
Unboxed: 42
CSHARP
object boxed = 42;
try
{
    double wrong = (double)boxed;
}
catch (InvalidCastException ex)
{
    Console.WriteLine($"Unbox type mismatch: {ex.Message}");
}
TEXT 📖 参照専用
Unbox type mismatch: Specified cast is not valid.

警告:アンボクシング操作におけるターゲット型は、元のボクシング型と完全に一致している必要があります。一致しない場合、InvalidCastException 例外がスローされます。


6. 型変換におけるよくある落とし穴

(1) 浮動小数点数から整数への変換に伴う精度の低下

CSHARP
double d = 9.99;
int i = (int)d;
Console.WriteLine($"9.99 → {i}");
TEXT 📖 参照専用
9.99 → 9

(2) ワイド型からナロー型へのオーバーフロー

CSHARP
long big = 5000000000L;
int small = (int)big;
Console.WriteLine($"5000000000L → {small}");
TEXT 📖 参照専用
5000000000L → 705032704

(3) 無効な文字列に対するParseThrowingの発生

CSHARP
try
{
    int n = int.Parse("3.14");
}
catch (FormatException)
{
    Console.WriteLine("Cannot parse \"3.14\" as int");
}
TEXT 📖 参照専用
Cannot parse "3.14" as int

ヒント - 落とし穴を避けるためのベストプラクティス:変換前にデータの範囲を確認すること;TryParseを優先して使用すること;オーバーフローが発生する可能性がある場合は、checkedキーワードを使用すること。

❓ よくある質問

Q 暗黙の型変換では、データが失われることは決してないのでしょうか?
A その通りです。暗黙の型変換は、精度や範囲が失われない安全な経路でのみ行われます。
Q Convert.ToInt32 と (int) による型変換の違いは何ですか?
A (int) は直接切り捨てますが、Convert.ToInt32 はバンカー丸めを用いて浮動小数点値を丸めます。
Q ボクシングとアンボクシングはパフォーマンスにどのような影響を与えますか?
A ボクシングはヒープ上にメモリを割り当てますが、アンボクシングには型チェックと値のコピーが必要です。これらの操作が頻繁に行われると、パフォーマンスが低下します。
Q int.Parse と Convert.ToInt32、どちらが優れていますか?
A 文字列の入力に関しては、両者の動作は似ていますが、Convert.ToInt32 は null の場合に 0 を返すのに対し、int.Parse は例外をスローします。
Q TryParse が失敗した場合、out パラメータの値はどうなりますか?
A その型のデフォルト値に設定されます。たとえば、int の場合は 0 になります。

📖 まとめ

📝 練習問題

  1. short の値 32767 を int に暗黙的に変換し、int の値 32768 を short に明示的にキャストするプログラムを作成し、その結果を確認してください。
  2. Convert.ToInt32 を使用して 2.5 と 3.5 を変換し、バンカーの丸め処理の挙動を確認する
  3. 文字列パラメータを受け取り、TryParse を使用してそれを安全に int として解析し、成功した場合は解析された値を返し、失敗した場合は -1 を返すメソッドを作成してください。
  4. ボクシングとアンボクシングを実演するコードを記述し、意図的に間違った型でアンボクシングを行い、InvalidCastExceptionをキャッチする
  5. オーバーフローを起こした int のキャストを checked キーワードで囲み、OverflowException がスローされるかどうかを確認する
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%