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

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

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

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

    Note

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

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

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

ここで説明したメソッドを示すコード例については、「方法:リフレクションを使用してジェネリック型をチェックおよびインスタンス化する」に記載された追加情報を参照してください。

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

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

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

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

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

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

型またはメソッドがオープンかクローズか

すべての型パラメーター (すべての内包する型のすべての型パラメーターを含む) がインスタンス化可能な型に置き換えられている場合、ジェネリック型またはジェネリック メソッドはクローズであるといいます。 ジェネリック型のインスタンスを作成できるのは、それがクローズである場合だけです。 型がオープンである場合、 Type.ContainsGenericParameters プロパティは true を返します。 メソッドの場合、 MethodBase.ContainsGenericParameters メソッドで同じ機能が実行されます。

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

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

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

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

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

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

型引数と型パラメーターの確認

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

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

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

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

ジェネリック型には、ジェネリック型の定義がないことがあります。その場合のジェネリック型はオープンであり、型引数と型パラメーターが混在しています。 たとえば、次のコードでは、クラス DD の 2 つ目の型パラメーターを Bの 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> {};  

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

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

ジェネリック型パラメーターのソースとしては、開発者が今調べている型、外側の型、またはジェネリック メソッドが考えられます。 ジェネリック型パラメーターのソースを特定するには、次の手順を実行します。

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

  • ソースがジェネリック メソッドでない場合は、 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を参照してください。

Title 説明
方法: リフレクションを使用してジェネリック型をチェックおよびインスタンス化する」を参照してください。 TypeMethodInfo のプロパティとメソッドを使用してジェネリック型について調べる方法を説明します。
ジェネリック ジェネリックの機能と .NET Framework におけるサポートについて説明します。
方法: リフレクション出力を使用してジェネリック型を定義する リフレクション出力を使用して動的アセンブリにジェネリック型を生成する方法について説明します。
型情報の表示 Type クラスについて説明します。また、Type をさまざまなリフレクション クラスと共に使用して、コンストラクター、メソッド、フィールド、プロパティ、およびイベントについての情報を取得する方法を示すコード例を提供します。