私はAsp.Net MVC のレッスンを受けていて、メソッドがコントローラーのアクションとして認定されることを学びました。
- 「オープンジェネリック型」であってはなりません
私はジェネリックをある程度理解し、ある程度使用していますが、
- .Netのオープン ジェネリック型とは何ですか。
- 閉じたジェネリック型のようなものはありますか?
- オープン ジェネリック型は、あまり使用されない用語です。何が使われていますか / それと混同されていますか?
私はAsp.Net MVC のレッスンを受けていて、メソッドがコントローラーのアクションとして認定されることを学びました。
私はジェネリックをある程度理解し、ある程度使用していますが、
C# 言語では、オープン型を、型引数または不明な型引数で定義されたジェネリック型のいずれかである型として定義します。
すべてのタイプは、開放型または閉鎖型のいずれかに分類できます。オープン型は、型パラメーターを含む型です。すなわち:
- 型パラメーターは、オープン型を定義します。
- 配列型は、その要素型がオープン型である場合にのみオープン型です。
- 構築された型は、その型引数の 1 つ以上がオープン型である場合にのみ、オープン型です。構築されたネストされた型は、その型引数の 1 つ以上、またはそれを含む型の型引数がオープン型である場合にのみ、オープン型です。
クローズドタイプは、オープンタイプではないタイプです。
したがってT
、List<T>
、 、Dictionary<string,T>
、およびDictionary<T,U>
はすべてオープン型 (T
およびU
は型引数) であるのに対し、List<int>
およびDictionary<string,int>
はクローズ型です。
関連する概念があります。バインドされていないジェネリック型は、型引数が指定されていないジェネリック型です。バインドされていない型は、それ以外の式では使用typeof()
できず、インスタンス化したり、そのメソッドを呼び出したりすることはできません。たとえば、List<>
andDictionary<,>
はバインドされていない型です。
オープン型と非バインド型の微妙な違いを明確にするには:
class Program {
static void Main() { Test<int>(); }
static void Test<T>() {
Console.WriteLine(typeof(List<T>)); // Print out the type name
}
}
このスニペットを実行すると、出力されます
System.Collections.Generic.List`1[System.Int32]
の CLR 名ですList<int>
。型引数が であることは実行時に明らかですSystem.Int32
。これによりList<T>
、バインドされたオープン タイプが作成されます。
実行時に、メソッドを使用してリフレクションを使用して、バインドされていないジェネリック型の未指定の型パラメーターに型引数をバインドできType.MakeGenericType
ます。
Type unboundGenericList = typeof(List<>);
Type listOfInt = unboundGenericList.MakeGenericType(typeof(int));
if (listOfInt == typeof(List<int>))
Console.WriteLine("Constructed a List<int> type.");
型がバインドされていないジェネリック型 (ジェネリック型定義) であるかどうかを確認できます。このジェネリック型からType.IsGenericTypeDefinition
プロパティを使用してバインドされた型を構築できます。
Console.WriteLine(typeof(Dictionary<,>).IsGenericTypeDefinition); // True
Console.WriteLine(typeof(Dictionary<int,int>).IsGenericTypeDefinition); // False
実行時に構築された型からバインドされていない型を取得するには、Type.GetGenericTypeDefinition
メソッドを使用できます。
Type listOfInt = typeof(List<int>);
Type list = listOfInt.GetGenericTypeDefinition(); // == typeof(List<>)
ジェネリック型の場合、完全にバインドされていない型定義または完全にバインドされた定義のいずれかを持つことができることに注意してください。一部の型パラメーターをバインドして、他のパラメーターをバインドしないままにすることはできません。たとえば、Dictionary<int,>
またはを持つことはできませんDictionary<,string>
。
ジェネリック型には 3 種類あります。簡単に言うと、この (簡略化された) 宣言では、次のようになります。
public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
Dictionary<TKey, TValue>
無制限のジェネリック型です。
KeyValuePair<TKey, TValue>
この場合、オープン構築されたジェネリック型です。いくつかの型パラメーターがありますが、それらは既に別の場所 (この場合は Dictionary) で定義されています。
Dictionary<string, int>
閉じて構築されたジェネリック型になります。