から派生するすべての型の定義はSystem.ValueType、 を除いてSystem.Enum、実際には 2 種類のものを定義します: ヒープ オブジェクト型とストレージ ロケーション型です。後者のインスタンスは暗黙のうちに前者に変換され (そこに含まれるデータのコピーを作成)、前者のインスタンスは明示的に後者に型キャストされます (同様に)。どちらの種類のものも同じSystem.Typeで記述され、メンバーは同じですが、動作が大きく異なります。
AList<AnyClassType>は、一連のヒープ オブジェクト参照を保持することを期待します。問題のリストがList<String>、List<StringBuilder>、List<Button>、またはその他のものであるかどうかは、リストのユーザーにとっては興味深いかもしれませんが、実際にはList<T>それ自体には興味がありません。List<Button>aを anにキャストすると、IEnumerable<Control>そのメソッドを呼び出す人は、GetEnumerator()から派生したヒープ オブジェクトへの参照を出力するオブジェクトを取得することを期待しますControl。からのリターンはList<Button>.GetEnumerator()その期待を満たします。対照的に、誰かが to をキャストした場合、List<Int32>呼び出しList<Object>た人GetEnumerator()は、ヒープ オブジェクト参照を出力するものを期待しますが、List<Integer>.GetEnumerator代わりに値型の整数を出力するものを生成します。
Int32値を aList<Object>または aに格納することができList<ValueType>ます。このようなリストに整数を格納すると、それがヒープ オブジェクト形式に変換され、それへの参照が格納されます。を呼び出すGetEnumerator()と、ヒープ参照を出力するものが生成されます。ただし、そのようなリストに に対応するヒープ タイプのインスタンスのみが含まれるように指定する方法はありませんInt32。C++/CLI では、「ヒープ格納値型への参照」型の変数を宣言できますが、.net のジェネリック型の背後にあるメカニズムは、そのような型では機能しません。