🥊
【C#】int → objectの裏側、ボクシング,アンボクシングとは【色々試してみた】
ボクシングとは
- 値型 → 参照型 への変換で暗黙的に発生する処理
- ヒープ割り当て + GC対象コピー発生のため、パフォーマンスの観点で望ましくない
int i = 10;
object o = i; //iの値がヒープにコピーされ、object参照が生成される
アンボクシングとは
- 参照型 → 値型への変換で発生する処理
- 明示的キャストを必要とする
- 失敗した場合は実行時に例外が発生する
object o = 10;
int i = (int)o;
アンボクシングで例外が起きる例
OK
object o = "hello";
string s = (string)o;
NG (InvalidCastException
)
- アンボクシング時、型が不一致の場合
InvalidCastException
が発生する
object o = "hello";
int i = (int)o; //例外発生
object o = 42;
long l = (long)o; //例外発生
public class MyClass { public int x = 1; }
public struct MyStruct { public int x; }
MyClass m = new();
MyStruct s = (MyStruct)o; // 例外発生
ボクシングと明示的キャストの違い
- メモリ上の扱いが異なる
- 明示的キャスト:同じ値型同士の変換(例:
float
→int
) - ボクシング:値型 → 参照型
実際に色々試してみた
使用したコード(トップレベルステートメントで作成)
Console.WriteLine("=== ボクシング: int → object ===");
int i = 123;
object boxed = i;
Console.WriteLine($"boxed: {boxed} (Type: {boxed.GetType()})");
Console.WriteLine("\n=== アンボクシング(成功): object → int ===");
int j = (int)boxed;
Console.WriteLine($"j: {j}");
Console.WriteLine("\n=== アンボクシング(失敗): ===");
try
{
object str = "hello";
int k = (int)str;
}
catch (InvalidCastException ex)
{
Console.WriteLine($"例外発生: {ex.Message}");
}
Console.WriteLine("\n=== ボクシング時の型と異なる型にアンボクシング ===");
try
{
object num = 42;
long l = (long)num;
}
catch (InvalidCastException ex)
{
Console.WriteLine($"例外発生: {ex.Message}");
}
Console.WriteLine("\n=== 値型同士のキャスト: float → int ===");
float f = 3.14f;
int fi = (int)f;
Console.WriteLine($"float -> int: {fi}");
Console.WriteLine("\n=== 等価比較でのエラー ===");
int m = 100;
object om = m;
Console.WriteLine($"m == (int)om: {m == (int)om}"); //問題なし
//Console.WriteLine($"om == m: {om == m}"); //エラー:参照型と値型の比較
参考
発展
余談
- System.Collectionsのコレクションは要素を
object
として格納するのでボクシングの影響すごそう
Discussion