1. ホーム
  2. c#

[解決済み] .NETの「オープンジェネリック型」とは何ですか?重複

2022-06-25 02:19:17

質問

私は Asp.Net MVCレッスン を読んでいて、あるメソッドがコントローラのアクションとして適格であることを学びました。

  • を持つものであってはなりません。 open generic type"

ジェネリックはなんとなく理解していて、ある程度は使っていますが。

  • とは何ですか? オープンな汎用型 を .Net で使用することです。
  • のようなものがあるのでしょうか? 閉じた汎用型 ?
  • オープンジェネリックタイプ はあまり使われない言葉です。何が使われているのか/混同されているのか?

どのように解決するのですか?

C#言語では、型引数か未知の型引数で定義された汎用型をオープン型と定義しています。

すべての型は、オープン型とクローズ型に分類することができます。An オープン型 は、型パラメータを含む型です。より具体的には

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

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

したがって T , List<T> そして Dictionary<string,T>Dictionary<T,U> はすべてオープン型 ( TU は型引数)であるのに対し 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]

のCLR名である List<int> . 実行時に、型引数が System.Int32 . このため List<T> a に束縛される のオープンタイプです。

実行時に、リフレクションを使って型引数を未束縛の汎用型の指定されていない型パラメータに束縛することができます。 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> .