この記事の英語版を表示するには、[英語] のチェック ボックスをオンにしてください。また、テキストにマウス ポインターを合わせると、ポップアップ ウィンドウに英語のテキストを表示することもできます。
翻訳
英語

Type.MakeGenericType メソッド

更新 : 2010 年 6 月

型の配列の要素を現在のジェネリック型定義の型パラメーターで置き換え、結果の構築型を表す Type オブジェクトを返します。

名前空間:  System
アセンブリ :  mscorlib (mscorlib.dll 内)

public virtual Type MakeGenericType(
	params Type[] typeArguments
)

パラメーター

typeArguments
型 : System.Type[]
現在のジェネリック型の型パラメーターに置き換えられる型の配列。

戻り値

型 : System.Type
typeArguments の要素を現在のジェネリック型の型パラメーターで置き換えることによって作られる構築型を表す Type

例外条件
InvalidOperationException

現在の型はジェネリック型定義を表しません。 つまり、IsGenericTypeDefinitionfalse を返します。

ArgumentNullException

typeArgumentsnull です。

または

typeArguments の要素が null です。

ArgumentException

typeArguments の要素の数が現在のジェネリック型定義の型パラメーターの数と同じではありません。

または

typeArguments の要素が、現在のジェネリック型の対応する型パラメーターに指定された制約を満たしていません。

または

typeArguments に含まれている要素が、ポインター型 (Type.IsPointertrue を返します)、ByRef 型 (Type.IsByReftrue を返します)、または Void です。

NotSupportedException

呼び出されたメソッドは、基本クラスではサポートされません。 派生クラスで実装を提供する必要があります。

MakeGenericType メソッドにより、ジェネリック型定義の型パラメーターに固有の型を割り当てるコードを記述して、特定の構築型を表す Type オブジェクトを作成できます。 この Type オブジェクトを使用して、構築型の実行時のインスタンスを作成できます。

MakeGenericType によって構築した型は開いた型にすることができます。つまり、これらの型の型引数のいくつかは、包含するジェネリック メソッドまたはジェネリック型の型パラメーターにすることができます。 動的なアセンブリを出力する場合に、このようなオープン構築型を使用する場合があります。 たとえば、次のコードの Base クラスや Derived クラスについて考えてみましょう。

public class Base<T, U> { }
public class Derived<V> : Base<int, V> { }

Derived を動的アセンブリに生成するには、基本型を構築する必要があります。 そのためには、ジェネリック型引数 Int32 および型パラメーター VDerived から使用して、クラス Base を表す TypeMakeGenericType メソッドを呼び出します。 型およびジェネリック型パラメーターは両方とも Type オブジェクトによって表されるので、両方を含む配列を MakeGenericType メソッドに渡すことができます。

メモメモ :

Base<int, V> などの構築型はコードの出力時には有用ですが、MakeGenericType メソッドをこの型で呼び出すことはできません。ジェネリック型定義ではないからです。 インスタンス化できるクローズ構築型を作成するには、最初に GetGenericTypeDefinition メソッドを呼び出して、ジェネリック型定義を表す Type オブジェクトを取得してから、目的の型引数を指定して MakeGenericType を呼び出します。

MakeGenericType によって返される Type オブジェクトは、結果の構築型の GetType メソッド、または同じ型引数を使って同じジェネリック型定義から作成された任意の構築型の GetType メソッドを呼び出して取得される Type と同じです。

メモメモ :

ジェネリック型の配列そのものはジェネリック型ではありません。 したがって、C<T>[] (Visual Basic の場合は Dim ac() As C(Of T)) のような配列型で MakeGenericType を呼び出すことはできません。 C<T>[] からクローズ ジェネリック型を構築するには、GetElementType を呼び出してジェネリック型定義 C<T> を取得し、ジェネリック型定義で MakeGenericType を呼び出して構築型を作成し、最後に構築型で MakeArrayType メソッドを呼び出して配列型を作成します。 ポインター型および ref 型 (Visual Basic では ByRef) でも同様です。

ジェネリック リフレクションで使用される用語の一定の条件の一覧については、IsGenericType のプロパティの解説を参照してください。

入れ子にされた型

ジェネリック型が C#、C++、または Visual Basic を使用して定義されている場合、入れ子にされた型はすべてジェネリックです。 入れ子にされた型がその型自体の型パラメーターを持っていない場合でも同様です。これら 3 種類の言語にはいずれも入れ子にされた型の型パラメーター リストに包含する型の型パラメーターが含まれているからです。 次のクラスについて考えてみましょう。

public class Outermost<T>
{
    public class Inner<U>
    {
        public class Innermost1<V> {}
        public class Innermost2 {}
    }
}

入れ子になったクラス Inner の型パラメーター リストには 2 つの型パラメーター (TU) が含まれています。最初の型パラメーターは、外側のクラスの型パラメーターです。 同様に、入れ子になったクラス Innermost1 の型パラメーター リストには 3 つの型パラメーター (TU、および V) が含まれています。TU は、外側のクラスの型パラメーターです。 入れ子になったクラス Innermost2 には 2 つの型パラメーター (TU) が含まれています。これらは外側のクラスの型パラメーターです。

包含する型のパラメーター リストに複数の型パラメーターが含まれている場合、入れ子にされた型の型パラメーター リストにはすべての型パラメーターが順番に含まれます。

入れ子にされた型のジェネリック型定義からジェネリック型を構築するには、すべての包含する型の型引数配列を連結して作られた配列を指定して MakeGenericType メソッドを呼び出します。この配列は一番外側がジェネリック型で始まり、入れ子にされた型の型引数配列で終了します (固有の型パラメーターを持っている場合)。 Innermost1 のインスタンスを作成するには、T、U、および V に割り当てられる 3 つの型を含む配列で MakeGenericType メソッドを呼び出します。 Innermost2 のインスタンスを作成するには、T および U に割り当てられる 2 つの型を含む配列で MakeGenericType メソッドを呼び出します。

このようにして各言語で包含する型の型パラメーターが反映されるので、包含する型の型パラメーターを使用して、入れ子にされた型のフィールドを定義できます。 そうでない場合は、型パラメーターは入れ子にされた型の本体内のスコープに入りません。 動的なアセンブリでコードを出力するか、または MSIL (Microsoft Intermediate Language) アセンブラーを使用すると、包含する型の型パラメーターを反映せずに、入れ子にされた型を定義することもできます。 次の MSIL アセンブラーのコードについて考えてみます。

.class public Outer<T> {
    .class nested public Inner<U> {
        .class nested public Innermost {
        }
    }
}

この例では、Innermost クラスの型 T または U のフィールドを定義できません。これらの型パラメーターはスコープ外だからです。 次のアセンブラー コードは、C++、Visual Basic、および C# で定義された場合と同じように動作する、入れ子になったクラスを定義しています。

.class public Outer<T> {
    .class nested public Inner<T, U> {
        .class nested public Innermost<T, U, V> {
        }
    }
}

MSIL 逆アセンブラーを使用して、高レベル言語で定義されている入れ子になったクラスを調べて、名前付けスキームを確認することができます。 逆アセンブラーの詳細については、.NET Framework のドキュメントの「MSIL 逆アセンブラー (Ildasm.exe)」を参照してください。

MakeGenericType メソッドを使用して、Dictionary<TKey, TValue> 型のジェネリック型定義から構築型を作成する例を次に示します。 構築型は、文字列キーで Test オブジェクト Dictionary<TKey, TValue> を表します。

メモメモ :

この例を実行するには、「Demo メソッドと TextBlock コントロールを使用したコード例のビルド」を参照してください。


using System;
using System.Reflection;
using System.Collections.Generic;

public class Example
{
   public static void Demo(System.Windows.Controls.TextBlock outputBlock)
   {
      outputBlock.Text += "\r\n--- Create a constructed type from the generic Dictionary type." + "\n";

      // Create a type object representing the generic Dictionary 
      // type, by omitting the type arguments (but keeping the 
      // comma that separates them, so the compiler can infer the
      // number of type parameters).      
      Type generic = typeof(Dictionary<,>);
      DisplayTypeInfo(outputBlock, generic);

      // Create an array of types to substitute for the type
      // parameters of Dictionary. The key is of type string, and
      // the type to be contained in the Dictionary is Example.
      Type[] typeArgs = { typeof(string), typeof(Example) };

      // Create a Type object representing the constructed generic
      // type.
      Type constructed = generic.MakeGenericType(typeArgs);
      DisplayTypeInfo(outputBlock, constructed);

      // Compare the type objects obtained above to type objects
      // obtained using typeof() and GetGenericTypeDefinition().
      outputBlock.Text += "\r\n--- Compare types obtained by different methods:" + "\n";

      Type t = typeof(Dictionary<String, Example>);
      outputBlock.Text += String.Format("\tAre the constructed types equal? {0}", t == constructed) + "\n";
      outputBlock.Text += String.Format("\tAre the generic types equal? {0}",
          t.GetGenericTypeDefinition() == generic) + "\n";
   }

   private static void DisplayTypeInfo(System.Windows.Controls.TextBlock outputBlock, Type t)
   {
      outputBlock.Text += String.Format("\r\n{0}", t) + "\n";

      outputBlock.Text += String.Format("\tIs this a generic type definition? {0}",
          t.IsGenericTypeDefinition) + "\n";

      outputBlock.Text += String.Format("\tIs it a generic type? {0}",
          t.IsGenericType) + "\n";

      Type[] typeArguments = t.GetGenericArguments();
      outputBlock.Text += String.Format("\tList type arguments ({0}):", typeArguments.Length) + "\n";
      foreach (Type tParam in typeArguments)
      {
         outputBlock.Text += String.Format("\t\t{0}", tParam) + "\n";
      }
   }
}

/* This example produces the following output:

--- Create a constructed type from the generic Dictionary type.

System.Collections.Generic.Dictionary`2[TKey,TValue]
        Is this a generic type definition? True
        Is it a generic type? True
        List type arguments (2):
                TKey
                TValue

System.Collections.Generic.Dictionary`2[System.String, Test]
        Is this a generic type definition? False
        Is it a generic type? True
        List type arguments (2):
                System.String
                Test

--- Compare types obtained by different methods:
        Are the constructed types equal? True
        Are the generic types equal? True
 */


Silverlight

サポート対象 : 5、4、3

Silverlight for Windows Phone

サポート対象 : Windows Phone OS 7.1、Windows Phone OS 7.0

XNA Framework

サポート対象 : Xbox 360、Windows Phone OS 7.0

Silverlight でサポートされるオペレーティング システムの詳細については、「サポートされているオペレーティング システムとブラウザー」を参照してください。

Date

[履歴]

Reason

2010 年 6 月

ArgumentException 例外の原因に関する情報が不足していたため追加しました。

カスタマー フィードバック

コミュニティの追加

追加
表示: