ボックス化は値型(intなど)を参照型(object)に変換する処理です。つまり、値をヒープ上のオブジェクトでラップします。アンボックス化はその逆で、値を取り出す処理です。どちらもパフォーマンスコスト(ヒープアロケーション、コピー)を伴い、これらを理解することで不要なオーバーヘッドを回避できます。
ボックス化とアンボックス化の実際
number = ;
boxed = number;
unboxed = ()boxed;
ボックス化は値型(intなど)を参照型(object)に変換する処理です。つまり、値をヒープ上のオブジェクトでラップします。アンボックス化はその逆で、値を取り出す処理です。どちらもパフォーマンスコスト(ヒープアロケーション、コピー)を伴い、これらを理解することで不要なオーバーヘッドを回避できます。
number = ;
boxed = number;
unboxed = ()boxed;
ボックス化はヒープに新しいオブジェクトを割り当て、値をコピーします。アンボックス化はその値をコピーして戻します。各ボックス化操作はヒープアロケーションです。単一の操作は安価ですが、ホットパスやループでは効果的に高くつきます。
// ❌ using a value type where an `object` is expected → implicit boxing
object obj = 42; // boxing
ArrayList list = new(); list.Add(42); // boxes (non-generic — stores object)
string s = string.Format("{0}", 42); // boxing for the object[] params
// these can box repeatedly in loops → significant GC pressure
ボックス化は暗黙的に発生することが多くあります。値型がobject(または非ジェネリックインターフェース)が期待される場所で使用されるたびに発生します。ループやホットパスでは、繰り返しボックス化により多くの短命なヒープオブジェクトが生成され、パフォーマンスが低下します。
// ❌ non-generic collection — boxes every value type added
ArrayList list = new();
list.Add(42); // boxes
// ✅ generic collection — NO boxing, type-safe
List<int> list = new();
list.Add(42); // no boxing — stored as int directly
主な対策はジェネリクスを使用することです(ArrayListの代わりにList<int>)。ジェネリクスは値型をボックス化なしで直接保存します。これは、古い非ジェネリックコレクションに対するジェネリクスの主要なパフォーマンス上の利点の1つです。
ボックス化とアンボックス化を理解することは、パフォーマンスの高いC#コードを書き、ジェネリクスがなぜ重要なのかを理解する上で重要です。
値型を参照型(object)に変換するボックス化には、ヒープアロケーションとコピーが必要であり、アンボックス化も値をコピーして戻すため、両者ともパフォーマンスコストを持ちます。
単一のボックス化操作は安価ですが、問題はボックス化が暗黙的に発生することです(値型がobjectが期待される場所で使用されるたびに)。また、ループやホットパスで繰り返し発生する可能性があり、多くの短命なヒープオブジェクトが生成され、GCプレッシャーが増加し、パフォーマンスが低下します。これは気付きやすい微妙なパフォーマンスの問題です。
実践的な要点は、ジェネリクスはボックス化を回避するということです。古い非ジェネリックArrayListの代わりにList<int>を使用すると、値型がボックス化なしで直接保存されます。これは、レガシーな非ジェネリックコレクションに対するジェネリクスの主要なパフォーマンス上の利点の1つであり、常にジェネリックコレクションを使用すべき主な理由です。
ボックス化とアンボックス化が何であるか、いつ発生するか(多くの場合は非表示)、そのパフォーマンスコスト(アロケーション、GCプレッシャー、特にループ内)、そしてジェネリクスがそれをどのように防ぐかを理解することは、効率的なC#を書くために重要な知識であり、ジェネリックコレクションが選好される理由を理解するために重要です。
ボックス化は一般的で微妙なパフォーマンスオーバーヘッドの原因であり、ジェネリクスを使用して回避することは基本的なパフォーマンスプラクティスであるため、ボックス化とアンボックス化を理解することは価値のある実用的な知識であり、パフォーマンスを意識したC#開発者を区別し、値型と参照型のモデルとジェネリクスの利点を理解していることを反映した頻出のインタビュー質問です。