web-dev-qa-db-ja.com

.NETの「オープンジェネリック型」とは何ですか?

Asp.Net MVCレッスン を実行していましたが、メソッドがコントローラーのアクションとして適格であるためには、

  • "一般型を開く"

私はジェネリックをある程度理解し、ある程度使用していますが、

  • .Netのopenジェネリック型とは何ですか.
  • 閉じたジェネリック型などはありますか?
  • 一般型を開くは、あまり使用されない用語です。それと何が使用され、混同されていますか?
112
Asad Butt

C#言語は、公開型を、型引数または未知の型引数で定義されたジェネリック型のいずれかである型として定義します。

すべてのタイプは、オープンタイプまたはクローズタイプのいずれかに分類できます。 open typeは、型パラメーターを含む型です。すなわち:

  • 型パラメーターは、公開型を定義します。
  • 配列型は、その要素型が公開型である場合にのみ、公開型です。
  • 構築型は、その型引数の1つ以上がopen type構築されたネストされたタイプは、1つ以上のそのタイプ引数またはそれを含むタイプのタイプ引数がオープンタイプ。

クローズドタイプは、オープンタイプではないタイプです。

したがって、T、_List<T>_、および_Dictionary<string,T>_、および_Dictionary<T,U>_はすべてオープン型です(TおよびUは型引数です) _List<int>_および_Dictionary<string,int>_は閉じた型です。

関連する概念があります:非バインドジェネリック型は、型引数が指定されていないジェネリック型です。非バインド型は、typeof()以外の式では使用できず、インスタンス化もメソッドの呼び出しもできません。たとえば、_List<>_と_Dictionary<,>_は非バインド型です。

オープン型と非バインド型の微妙な違いを明確にするには:

_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]
_

これは_List<int>_のCLR名です。実行時に、type引数が_System.Int32_であることは明らかです。これにより、_List<T>_はboundオープン型になります。

実行時に、リフレクションを使用して、 _Type.MakeGenericType_ method を使用して、型引数をバインドされていないジェネリック型の指定されていない型パラメーターにバインドできます。

_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_ method を使用できます。

_Type listOfInt = typeof(List<int>);
Type list = listOfInt.GetGenericTypeDefinition(); // == typeof(List<>)
_

ジェネリック型の場合、完全にバインドされていない型定義または完全にバインドされた定義のいずれかを使用できます。一部の型パラメーターをバインドし、他のパラメーターをバインドしないままにすることはできません。たとえば、_Dictionary<int,>_または_Dictionary<,string>_を使用することはできません。

186
Mehrdad Afshari

追加するだけ:

Dictionary<string, T>(より正確にはDictionary<string,>)はまだオープン型です。

例:

void Foo<T>(Dictionary<string,T> dic) { ... }
9
leppie

「オープンジェネリック型」は、その型がまだ指定されていないジェネリック型です(例、_CargoCrate<T>_)。具体的な型が割り当てられると、「クローズ」になります(例、_CargoCrate<Widget>_)。

たとえば、次のようなものがあるとします。

_public class Basket<T> {
  T[] basketItems;
}

public class PicnicBlanket<T> {
  Basket<T> picnicBasket;   // Open type here. We don't know what T is.
}

                                 // Closed type here: T is Food.
public class ParkPicnicBlanket : PicnicBlanket<Food> {
}
_

ここでは、picnicBasketの型が開いています。Tにはまだ何も割り当てられていません。特定のタイプで具体的なPicnicBlanketを作成する場合、たとえばPicnicBlanket<Food> p = new PicnicBlanket<Food>()を記述することでclosedと呼ぶようになりました。

6
John Feminella

ジェネリック型には3種類あります。短くするには、この(簡略化された)宣言で:

public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
  • Dictionary<TKey, TValue>無制限のジェネリック型です。

  • KeyValuePair<TKey, TValue>は、この場合、オープン構築ジェネリック型です。型パラメーターはいくつかありますが、それらは他の場所(この場合は辞書内)で既に定義されています。

  • Dictionary<string, int>は、クローズドジェネリックジェネリックタイプです。

5
Gorpik