.net ランタイム内では、すべての値の型に同じ名前の関連付けられたヒープ オブジェクト型があります。一部のコンテキストでは、値の型が使用されます。他のコンテキストでは、ヒープ タイプ。値型の格納場所 (変数、パラメータ、戻り値、フィールド、または配列スロット) が宣言されると、その格納場所はその型の実際の内容を保持します。クラス型の格納場所が宣言されると、それは、null
または別の場所に格納されているヒープ オブジェクトへの参照を保持します。インターフェイス型の格納場所は、参照型の格納場所のように扱われ、インターフェイスの実装の一部 (またはすべて) が実際には値型であっても、ヒープ参照を保持します。
値の型を参照型の格納場所に格納しようとすると、システムはその値の型に関連付けられたヒープ型の新しいインスタンスを作成し、すべてのフィールドを元の格納場所から新しいインスタンスの対応するフィールドにコピーします。そのインスタンスへの参照を保存します。これは「ボクシング」と呼ばれるプロセスです。ヒープ参照を値型の格納場所にキャストしようとすると、値型に関連付けられたヒープ型のインスタンスを参照しているかどうかがチェックされます。その場合、ヒープ オブジェクトのフィールドは、値型の格納場所にある対応するフィールドにコピー (「ボックス化解除」) されます。
のような型がSystem.Int32
から派生したように見えるかもしれませんがSystem.Object
、それは半分しか当てはまりません。System.Int32
から派生したヒープオブジェクト type がありSystem.Object
ますが、 type の変数はSystem.Int32
そのようなオブジェクトへの参照を保持しません。代わりに、そのような変数は、その整数に関連付けられた実際のデータを保持します。データ自体は単なるビットの集まりであり、何からも派生していません。
インターフェイス型の格納場所を「インターフェイス_を実装する System.Object から派生したもの」を保持していると考えると、そのインターフェイスを実装する任意のクラス型のインスタンスはその型のインスタンスですが、値型のインスタンスであっても、それらが他の型に変換可能である場合、他の型のインスタンスではありません。を使用するコードは、そのメソッドが、または implementsに変換できるものを返すことIEnumerator<IFoo>
だけを望んでいません。そのimplementsの派生物である何かを返すことを望んでいます。したがって、 をに置き換えるには、両方を実装するように制約する必要があります。Current
IFoo
IFoo
Object
IFoo
IEnumerable<T>
IEnumerable<IFoo>
T
IFoo
と の適切な導関数になりSystem.Object
ます。