ヒープに格納されたすべての非配列非文字列オブジェクトには、8 または 16 バイトのヘッダー (32/64 ビット システムのサイズ) が含まれ、その後にそのオブジェクトのパブリック フィールドとプライベート フィールドの内容が続きます。配列と文字列には、上記のヘッダーに加えて、配列の長さと各要素のサイズ (場合によっては次元数、追加の各次元の長さなど) を定義するバイトがいくつかあり、その後に最初のすべてのフィールドが続きます。オブジェクトへの参照が与えられると、システムはヘッダーを簡単に調べて、それがどのタイプであるかを判断できます。
参照型の格納場所には、ヒープに格納されているオブジェクトを一意に識別する 4 バイトまたは 8 バイトの値が保持されます。現在の実装では、その値はポインターですが、「オブジェクト ID」と考える方が簡単です (意味的に同等です)。
値型の格納場所には、値型のフィールドの内容が保持されますが、関連するヘッダーはありません。コードが type の変数を宣言する場合、それが何であるかInt32
を示す情報を保存する必要はありません。Int32
その場所が保持するという事実Int32
は、プログラムの一部として効果的に保存されるため、場所自体に保存する必要はありません。たとえば、それぞれが type のフィールドを持つ 100 万個のオブジェクトがある場合、これは大きな節約になりますInt32
。を保持する各オブジェクトにInt32
は、それを操作できるクラスを識別するヘッダーがあります。そのクラス コードの 1 つのコピーは、フィールドがInt32
コードの一部であることは、それらのフィールドのすべてのストレージにそれが何であるかに関する情報を含めるよりもはるかに効率的です。
値型の格納場所の内容を、その特定の値型を期待することを知らないコードに渡す要求が行われる場合、ボクシングが必要です。未知の型のオブジェクトを予期するコードは、ヒープに格納されたオブジェクトへの参照を受け入れることができます。ヒープに格納されたすべてのオブジェクトには、そのオブジェクトのタイプを識別するヘッダーがあるため、コードは、そのタイプを知る必要がある方法でオブジェクトを使用する必要がある場合はいつでも、そのヘッダーを使用できます。
.net では、ジェネリック クラスおよびメソッドと呼ばれるものを宣言できることに注意してください。このような各宣言は、動作することが期待されるオブジェクトのタイプを除いて同一のクラスまたはメソッドのファミリを自動的に生成します。Int32
ルーチンにを渡すと、型のすべてのインスタンスが効果的に に置き換えられDoSomething<T>(T param)
たバージョンのルーチンが自動的に生成されます。そのバージョンのルーチンは、type として宣言されたすべての格納場所が を保持していることを認識します。そのため、ルーチンが格納場所を使用するようにハードコードされている場合と同様に、それらの場所自体に型情報を格納する必要はありません。T
Int32
T
Int32
Int32