リフレクションの観点から見ると、ジェネリック型と通常の型の違いは、ジェネリック型が一連の型パラメーター (ジェネリック型定義の場合) または型引数 (構築された型の場合) に関連付けられているということです。 ジェネリック メソッドは、同じ方法で通常のメソッドとは異なります。
リフレクションがジェネリック型とメソッドを処理する方法を理解するには、次の 2 つのキーがあります。
ジェネリック型定義とジェネリック メソッド定義の型パラメーターは、 Type クラスのインスタンスによって表されます。
注
Type オブジェクトがジェネリック型パラメーターを表す場合、Typeの多くのプロパティとメソッドの動作が異なります。 これらの違いについては、プロパティとメソッドの記事に記載されています。 たとえば、「 IsAutoClass と DeclaringType」を参照してください。 さらに、一部のメンバーは、 Type オブジェクトがジェネリック型パラメーターを表す場合にのみ有効です。 例については、「 GetGenericTypeDefinition」を参照してください。
Typeのインスタンスがジェネリック型を表す場合は、型パラメーター (ジェネリック型定義の場合) または型引数 (構築された型の場合) を表す型の配列が含まれます。 ジェネリック メソッドを表す MethodInfo クラスのインスタンスについても同様です。
リフレクションには、型パラメーターの配列にアクセスし、Typeのインスタンスが型パラメーターと実際の型のどちらを表すかを判断できる、MethodInfoとTypeのメソッドが用意されています。
ここで説明するメソッドを示すコード例については、「 方法: リフレクションを使用してジェネリック型を調べてインスタンス化する」を参照してください。
次の説明では、型パラメーターと引数の違い、オープンまたはクローズの構築型の違いなど、ジェネリックの用語に精通していることを前提としています。 詳細については、「 ジェネリック」を参照してください。
これはジェネリック型またはメソッドですか?
リフレクションを使用して、 Typeのインスタンスで表される不明な型を調べる場合は、 IsGenericType プロパティを使用して、不明な型がジェネリックかどうかを判断します。 型がジェネリックの場合は true
を返します。 同様に、 MethodInfo クラスのインスタンスによって表される不明なメソッドを調べる場合は、 IsGenericMethod プロパティを使用して、メソッドがジェネリックかどうかを判断します。
これはジェネリック型またはメソッド定義ですか?
IsGenericTypeDefinition プロパティを使用して、Type オブジェクトがジェネリック型定義を表しているかどうかを判断し、IsGenericMethodDefinition メソッドを使用して、MethodInfoがジェネリック メソッド定義を表しているかどうかを判断します。
ジェネリック型とメソッド定義は、インスタントな型の作成元となるテンプレートです。 .NET ライブラリ内のジェネリック型 ( Dictionary<TKey,TValue>など) は、ジェネリック型定義です。
型またはメソッドは開いているか閉じているか。
ジェネリック型またはメソッドは、すべての型パラメーターに、外側の型のすべての型パラメーターを含めたインスタンス化可能な型が置き換えられた場合にクローズされます。 ジェネリック型のインスタンスは、閉じている場合にのみ作成できます。
Type.ContainsGenericParameters プロパティは、型が開いている場合にtrue
を返します。 メソッドの場合、 MethodBase.ContainsGenericParameters メソッドは同じ関数を実行します。
閉じたジェネリック型を生成する
ジェネリック型またはメソッド定義を作成したら、 MakeGenericType メソッドを使用して閉じたジェネリック型を作成するか、 MakeGenericMethod メソッドを使用して、閉じたジェネリック メソッドの MethodInfo を作成します。
ジェネリック型またはメソッド定義を取得する
ジェネリック型またはメソッド定義ではないオープン ジェネリック型またはメソッドがある場合、そのインスタンスを作成することはできません。また、不足している型パラメーターを指定することはできません。 ジェネリック型またはメソッド定義が必要です。 GetGenericTypeDefinition メソッドを使用してジェネリック型定義を取得するか、GetGenericMethodDefinition メソッドを使用してジェネリック メソッド定義を取得します。
たとえば、Typeを表すDictionary<int, string>
オブジェクトがあり、型Dictionary<string, MyClass>
を作成する場合は、GetGenericTypeDefinition メソッドを使用してTypeを表すDictionary<TKey, TValue>
を取得し、MakeGenericType メソッドを使用してTypeを表すDictionary<int, MyClass>
を生成できます。
ジェネリック型ではないオープン ジェネリック型の例については、「 型パラメーターまたは型引数」を参照してください。
型引数と型パラメーターを調べる
Type.GetGenericArguments メソッドを使用して、ジェネリック型の型パラメーターまたは型引数を表すType オブジェクトの配列を取得し、MethodInfo.GetGenericArguments メソッドを使用してジェネリック メソッドに対して同じ操作を行います。
Type オブジェクトが型パラメーターを表すことがわかっている場合は、リフレクションが回答できる追加の質問が多数あります。 型パラメーターのソース、位置、および制約を決定できます。
型パラメーターまたは型引数
配列の特定の要素が型パラメーターか型引数かを判断するには、 IsGenericParameter プロパティを使用します。 要素が型パラメーターの場合、 IsGenericParameter プロパティは true
。
ジェネリック型は、ジェネリック型定義なしで開くことができます。その場合、型引数と型パラメーターの組み合わせがあります。 たとえば、次のコードでは、クラス D
は、D
の 2 番目の型パラメーターに対して B
の最初の型パラメーターを置き換えて作成された型から派生します。
class B<T, U> {}
class D<V, W> : B<int, V> {}
Class B(Of T, U)
End Class
Class D(Of V, W)
Inherits B(Of Integer, V)
End Class
Typeを表すD<V, W>
オブジェクトを取得し、BaseType プロパティを使用してその基本型を取得すると、結果のtype B<int, V>
は開きますが、ジェネリック型定義ではありません。
ジェネリック パラメーターのソース
ジェネリック型パラメーターは、調べている型、外側の型、またはジェネリックメソッドに由来することがあります。 ジェネリック型パラメーターのソースは、次のように決定できます。
- まず、 DeclaringMethod プロパティを使用して、型パラメーターがジェネリック メソッドから取得されるかどうかを判断します。 プロパティ値が null 参照でない場合、ソースはジェネリック メソッドです。
- ソースがジェネリック メソッドでない場合は、 DeclaringType プロパティを使用して、ジェネリック型パラメーターが属するジェネリック型を判断します。
型パラメーターがジェネリック メソッドに属している場合、 DeclaringType プロパティはジェネリック メソッドを宣言した型を返します。これは無関係です。
ジェネリック パラメーターの位置
まれな状況では、宣言するクラスの型パラメーター リスト内の型パラメーターの位置を決定する必要があります。 たとえば、前の例のType型を表すB<int, V>
オブジェクトがあるとします。
GetGenericArguments メソッドでは、型引数の一覧が提供されます。V
調べると、DeclaringMethodプロパティとDeclaringTypeプロパティを使用して、それがどこから来ているかを検出できます。 その後、 GenericParameterPosition プロパティを使用して、定義された型パラメーター リスト内の位置を決定できます。 この例では、 V
は、定義された型パラメーター リストの位置 0 (ゼロ) にあります。
基本型とインターフェイスの制約
GetGenericParameterConstraints メソッドを使用して、型パラメーターの基本型制約とインターフェイス制約を取得します。 配列の要素の順序は重要ではありません。 要素がインターフェイス型の場合、要素はインターフェイス制約を表します。
ジェネリック パラメーター属性
GenericParameterAttributes プロパティは、分散 (共変性または反変性) と型パラメーターの特殊な制約を示すGenericParameterAttributes値を取得します。
共変性と反変性
型パラメーターが共変か反変かを判断するには、GenericParameterAttributes.VarianceMask プロパティによって返されるGenericParameterAttributes値にGenericParameterAttributes マスクを適用します。 結果が GenericParameterAttributes.None場合、型パラメーターは不変です。 詳細については、「 共変性と反変性」を参照してください。
特別な制約
型パラメーターの特殊な制約を判断するには、GenericParameterAttributes.SpecialConstraintMask プロパティによって返されるGenericParameterAttributes値にGenericParameterAttributes マスクを適用します。 結果が GenericParameterAttributes.None場合、特別な制約はありません。 型パラメーターは、参照型、null 非許容値型、およびパラメーターなしのコンストラクターに制限できます。
不変量
ジェネリック型のリフレクションにおける一般的な用語の不変条件の表については、 Type.IsGenericTypeを参照してください。 ジェネリック メソッドに関連するその他の用語については、 MethodBase.IsGenericMethodを参照してください。
.NET