型システムの正確な詳細は実装に依存しますが、それが依存しているので気にしないでくださいと述べるだけでなく、もう少し詳しく説明します。ジェフリー・リッチターによる「 C#経由のCLR 」という本と、ハヌ・コンマラパティらによる「CLRがランタイムオブジェクトを作成する方法」の記事に従って、Microsoftの実装(.NET)でおおよそどのように機能するかを説明します。(元のMSDN 2005年5月号)。
クラスがあるとしましょう:
class Foo
{
// Instance fields
string myBar = "Foobar";
int myNum;
// Static fields
static string bar = "Foobar";
static int num;
}
Foo myFoo = new Foo();
Type typeOfFoo = typeof(Foo);
インスタンスフィールドはどこにありますか?
と言うとnew Foo()
、オブジェクトインスタンスにスペースが割り当てられて初期化され、コンストラクターが呼び出されます。このインスタンスは、下の画像にFooのインスタンスとして示されています。たとえば、instanceには、クラスのインスタンスフィールド(この場合はmyBar
and myNum
)のみが含まれ、ヒープに割り当てられたオブジェクトの場合、ランタイム(Sync block index
およびType handle
)によって使用される2つの追加フィールドが含まれます。タイプハンドルは、インスタンスのタイプ(この場合はFooType
のタイプ)を記述するオブジェクトへのポインターです。
もう一度言うnew Foo()
と、新しいスペースが割り当てられ、そのタイプのインスタンスフィールド用のスペースが再び含まれます。ご覧のとおり、インスタンスフィールドはオブジェクトインスタンスに関連付けられています。
ランタイムは、各インスタンスフィールドを、オブジェクトのデータの先頭から固定されたオフセットに配置します。たとえば、myBar
オフセット+4に住んでいる可能性があります。インスタンスフィールドのアドレスは、単にオブジェクトのアドレスにフィールドのオフセットを加えたものです。
静的フィールドはどこにありますか?
C#およびJavaの静的フィールドは、オブジェクトインスタンスではなく、型に関連付けられています。クラス、構造体、列挙型はタイプの例です。静的フィールドの値を保持するために割り当てられるスペースは、(タイプごとに)1回だけです。タイプごとにオブジェクトType
が1つしかないため、タイプを説明する構造内の静的フィールドにスペースを割り当てることは理にかなっています。Type
これは、C#とJavaで採用されているアプローチです。
Type
オブジェクト1は、タイプがランタイムによってロードされるときに作成されます。この構造には、ランタイムが新しいインスタンスを割り当てたり、メソッドを呼び出したり、キャストを実行したりするために必要なあらゆる種類の情報が含まれています。また、静的フィールド(この場合はbar
と)用のスペースも含まれていますnum
。
ランタイムは、タイプのデータの先頭からオフセットして各静的フィールドを配置しました。これはタイプごとに異なります。たとえば、bar
オフセット+64で動作する可能性があります。静的フィールドのアドレスは、Type
オブジェクトのアドレスにフィールドのオフセットを加えたものです。タイプは静的に既知です。

1)Microsoft .NETでは、複数の異なる構造体が、MethodTableやEEClass構造体などの型を記述します。