リフレクションとジェネリック型

リフレクションの観点から言えば、ジェネリック型は、それがジェネリック型定義である場合は型パラメーター セットが、構築された型である場合は型引数セットが関連付けられているという点で通常の型と異なります。 ジェネリック メソッドも同じように通常のメソッドと異なります。

リフレクションでジェネリック型とジェネリック メソッドを処理するしくみを理解するうえで、次の 2 つの点が重要となります。

  • ジェネリック型の定義とジェネリック メソッドの定義の型パラメーターは、Type クラスのインスタンスによって表されます。

    メモメモ

    Type オブジェクトがジェネリック型パラメーターを表す場合、Type の多数のプロパティとメソッドにはさまざまな動作があります。これらの相違点については、該当のプロパティおよびメソッドに関するトピックに記載されています。たとえば、IsAutoClass および DeclaringType のトピックを参照してください。また、一部のメンバーは、Type オブジェクトがジェネリック型パラメーターを表す場合にのみ有効です。たとえば、「GetGenericTypeDefinition」を参照してください。

  • Type のインスタンスがジェネリック型を表す場合、そのインスタンスには、型パラメーター (ジェネリック型の定義の場合) または型引数 (構築された型の場合) を表す型の配列が含まれます。 これは、ジェネリック メソッドを表す MethodInfo クラスのインスタンスの場合も同様です。

リフレクションが提供する Type および MethodInfo のメソッドを使用すると、型パラメーターの配列にアクセスしたり、Type のインスタンスが型パラメーターと実際の型のどちらを表しているかを確認したりできます。

ここで説明するメソッドを示すプログラム例については、「方法 : リフレクションを使用してジェネリック型をチェックおよびインスタンス化する」を参照してください。

以下の説明は、型パラメーターと型引数の違いや、オープン構築型とクローズ構築型の違いなど、ジェネリックの用語を十分に理解していることを前提としています。 詳細については、「.NET Framework におけるジェネリック」を参照してください。

この概要は、次のセクションで構成されています。

  • ジェネリック型またはジェネリック メソッドかどうかの確認

  • クローズ ジェネリック型の生成

  • 型引数と型パラメーターのチェック

  • 一定の条件

  • 関連トピック

ジェネリック型またはジェネリック メソッドかどうかの確認

リフレクションを使用して、Type のインスタンスによって表される不明な型を調べる場合は、IsGenericType プロパティを使用してその不明な型がジェネリックかどうかを確認します。 型がジェネリックの場合、このプロパティは true を返します。 同様に、MethodInfo クラスのインスタンスによって表される不明なメソッドを調べる場合には、IsGenericMethod プロパティを使用してそのメソッドがジェネリックかどうかを確認します。

ジェネリック型の定義またはジェネリック メソッドの定義かどうかの確認

Type オブジェクトがジェネリック型の定義を表しているかどうかを確認するには、IsGenericTypeDefinition プロパティを使用します。また、MethodInfo がジェネリック メソッドの定義を表しているかどうかを確認するには、IsGenericMethodDefinition メソッドを使用します。

ジェネリック型の定義とジェネリック メソッドの定義は、インスタンス化可能な型の作成元となるテンプレートです。 Dictionary<TKey, TValue> など、.NET Framework クラス ライブラリのジェネリック型はジェネリック型の定義です。

型またはメソッドが開いているか閉じているか

すべての型パラメーターがインスタンス化可能な型に置き換えられている場合、ジェネリック型またはジェネリック メソッドは閉じています。 ジェネリック型が閉じている場合、作成できるのはジェネリック型のインスタンスだけです。 型が開いている場合、Type.ContainsGenericParameters プロパティは true を返します。 メソッドの場合、MethodInfo.ContainsGenericParameters メソッドは同じ関数を実行します。

ページのトップへ

クローズ ジェネリック型の生成

ジェネリック型の定義を取得したら、MakeGenericType メソッドを使用してクローズ ジェネリック型を作成します。また、ジェネリック メソッドの定義を取得したら、MakeGenericMethod メソッドを使用して閉じたジェネリック メソッドの MethodInfo を作成します。

ジェネリック型またはジェネリック メソッドの定義の取得

ジェネリック型またはジェネリック メソッドの定義ではないオープン ジェネリック型またはジェネリック メソッドの場合、そのインスタンスを作成することはできません。また、欠落した型パラメーターを指定することもできません。 ジェネリック型またはジェネリック メソッドの定義が必要です。 ジェネリック型の定義を取得するには、GetGenericTypeDefinition メソッドを使用します。また、ジェネリック メソッドの定義を取得するには、GetGenericMethodDefinition メソッドを使用します。

たとえば、Dictionary<int, string> (Visual Basic では Dictionary(Of Integer, String)) を表す Type オブジェクトがあり、Dictionary<string, MyClass> 型を作成する場合、GetGenericTypeDefinition メソッドを使用して Dictionary<TKey, TValue> を表す Type を取得し、MakeGenericType メソッドを使用して Dictionary<int, MyClass> を表す Type を作成します。

ジェネリック型ではないオープン ジェネリック型の例については、このトピックの「型パラメーターまたは型引数」を参照してください。

ページのトップへ

型引数と型パラメーターのチェック

ジェネリック型の型パラメーターまたは型引数を表す Type オブジェクトの配列を取得するには、Type.GetGenericArguments メソッドを使用します。ジェネリック メソッドの場合は、MethodInfo.GetGenericArguments メソッドを使用します。

Type オブジェクトが型パラメーターを表していることがわかったら、リフレクションによって他の詳細も確認できます。 型パラメーターのソース、位置、および制約を確認できます。

型パラメーターまたは型引数

配列の特定の要素が型パラメーターと型引数のどちらであるかを確認するには、IsGenericParameter プロパティを使用します。 要素が型パラメーターの場合、IsGenericParameter プロパティは true です。

ジェネリック型の定義がない場合、ジェネリック型は開いている可能性があります。この場合、そのジェネリック型には型引数と型パラメーターが混在しています。 たとえば、次のコードでは、D クラスは B の 2 つ目の型パラメーターを D の 1 つ目の型パラメーターに置き換えることによって作成された型から派生します。

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
generic<typename T, typename U> ref class B {};
generic<typename V, typename W> ref class D : B<int, V> {};

D<V, W> を表す Type オブジェクトを取得し、BaseType プロパティを使用してその基本型を取得した場合、結果として得られた type B<int, V> は開いていますが、ジェネリック型の定義ではありません。

ジェネリック パラメーターのソース

ジェネリック型パラメーターのソースは、開発者が調べた型、外側の型、またはジェネリック メソッドのいずれかです。 ジェネリック型パラメーターのソースは、次の手順で確認できます。

  • まず、DeclaringMethod プロパティを使用して、型パラメーターのソースがジェネリック メソッドかどうかを確認します。 プロパティ値が null 参照 (Visual Basic では Nothing) ではない場合、ソースはジェネリック メソッドです。

  • ソースがジェネリック メソッドではない場合は、DeclaringType プロパティを使用して、そのジェネリック型パラメーターが属するジェネリック型を確認します。

型パラメーターがジェネリック メソッドに属している場合、DeclaringType プロパティはそのジェネリック メソッドを宣言した型を返しますが、これは無関係です。

ジェネリック パラメーターの位置

まれなケースですが、宣言するクラスの型パラメーター リスト内の型パラメーターの位置を確認することが必要な場合があります。 たとえば、前述の例の B<int, V> 型を表す Type オブジェクトがあるとします。 GetGenericArguments メソッドは、型引数のリストを提供します。V を調べるときには、DeclaringMethod プロパティと DeclaringType プロパティを使用して、ソースを確認できます。 次に、GenericParameterPosition プロパティを使用して、型パラメーターが定義された型パラメーター リスト内の位置を確認できます。 この例では、V は、定義された型パラメーター リスト内の 0 (ゼロ) の位置にあります。

基本型の制約とインターフェイスの制約

型パラメーターの基本型の制約とインターフェイスの制約を取得するには、GetGenericParameterConstraints メソッドを使用します。 配列の要素の順序は重要ではありません。 要素がインターフェイス型の場合、その要素はインターフェイスの制約を表します。

ジェネリック パラメーター属性

GenericParameterAttributes プロパティは、型パラメーターの分散 (共変性または反変性) および特殊な制約を示す GenericParameterAttributes 値を取得します。

共変性と反変性

型パラメーターが共変性であるか反変性であるかどうかを確認するには、GenericParameterAttributes プロパティから返される GenericParameterAttributes 値に GenericParameterAttributes.VarianceMask マスクを適用します。 結果が GenericParameterAttributes.None の場合、型パラメーターは不変です (共変性でも反変性でもありません)。 「ジェネリックの共変性と反変性」を参照してください。

特殊な制約

型パラメーターの特殊な制約を確認するには、GenericParameterAttributes プロパティから返される GenericParameterAttributes 値に GenericParameterAttributes.SpecialConstraintMask マスクを適用します。 結果が GenericParameterAttributes.None の場合、特殊な制約はありません。 型パラメーターは、参照型、null 非許容値型、および既定のコンストラクターを持つように制約できます。

ページのトップへ

一定の条件

ジェネリック型のリフレクションの一般的な用語に関する一定の条件の一覧については、Type.IsGenericType に関するトピックを参照してください。 ジェネリック メソッドに関連する他の用語については、MethodInfo.IsGenericMethod に関するトピックを参照してください。

ページのトップへ

関連トピック

タイトル

説明

方法 : リフレクションを使用してジェネリック型をチェックおよびインスタンス化する

Type および MethodInfo のプロパティとメソッドを使用してジェネリック型をチェックする方法を示します。

.NET Framework におけるジェネリック

ジェネリック機能、および .NET Framework でジェネリック機能がどのようにサポートされるかについて説明します。

方法: リフレクション出力を使用してジェネリック型を定義する

リフレクション出力を使用して動的アセンブリでジェネリック型を生成する方法を示します。

型情報の表示

Type クラスについて説明します。Type をさまざまなリフレクション クラスと共に使用して、コンストラクター、メソッド、フィールド、プロパティ、およびイベントについての情報を取得する方法を示すコード例を提供します。

ページのトップへ