私が理解しているように、C#/.Net ジェネリックはある程度の具体化をサポートしています。したがって、次のコードがあるとします。
List<int> list = new List<int>();
list.Add(1);
値 1 は自動ボックス化されますか、それとも「リスト」オブジェクトはプリミティブ int を効率的に処理しますか?
私が理解しているように、C#/.Net ジェネリックはある程度の具体化をサポートしています。したがって、次のコードがあるとします。
List<int> list = new List<int>();
list.Add(1);
値 1 は自動ボックス化されますか、それとも「リスト」オブジェクトはプリミティブ int を効率的に処理しますか?
いいえ、箱入りにはなりません。実行時に、 のバッキング配列List<int>
は本当に になりますint[]
。これは、本物のプリミティブ型だけに当てはまるわけではないことに注意してください。どのList<T>
値型の値もボックス化しません(ではなく etcとして宣言されていると仮定します)。List<Guid>
List<object>
基本的に、.NET のジェネリックは、Java よりも多くの情報を保持します。CLR は、ジェネリックをネイティブに理解し、適切に処理します。Java では、JVM がジェネリックをほとんど認識していません。
たとえば、次のように記述します。
object list = new List<string>();
Type type = list.GetType();
それからtype
等しいtypeof(List<string>)
- そしてそれは(言う)List<Guid>
などとは異なります.
値はint
リスト内でボックス化されません。これは、ジェネリックの優れた点の 1 つであり、コンパイラ (具体的には JIT コンパイラ) が、値を として格納するのではなく、クラスの型付きバージョンを構築することです。したがって、公開されたメソッドとプロパティを通じて型の安全性を強制するだけでなく、すべての面で真に型付けされます。List<>
object
他の人が指摘したように、ジッターは、新しい値の型を含むすべての構造に対して新しいコードを生成します。まだ言及されていない興味深い点は、ジッターが参照型の構築に対して一度コードを生成し、それをすべての参照型に対して再利用することです。のコードList<object>
は のコードとまったく同じですList<string>
。
ばかげているように聞こえるかもしれませんが、ジェネリックはテンプレートではないことを覚えておいてください。ジェネリック メソッド本体 IL のコードが発行されるまでに、オーバーロードの解決とその他の関連するセマンティック分析は、C# コンパイラによって既に行われています。
.NETジェネリックは構造体に特化しているため、あなたのケースではボクシングは必要ありません。とにかくキャストする必要がないことに注意してください。