방법: 리플렉션을 사용하여 제네릭 형식 검사 및 인스턴스화How to: Examine and Instantiate Generic Types with Reflection

다른 형식에 대한 정보와 동일한 방식으로 제네릭 형식에 대한 정보를 가져올 수 있습니다. 제네릭 형식을 나타내는 Type 개체를 검사하면 됩니다.Information about generic types is obtained in the same way as information about other types: by examining a Type object that represents the generic type. 원칙의 차이점은 제네릭 형식에는 제네릭 형식 매개 변수를 나타내는 Type 개체 목록이 있다는 것입니다.The principle difference is that a generic type has a list of Type objects representing its generic type parameters. 이 섹션의 첫 번째 절차에서는 제네릭 형식을 검사합니다.The first procedure in this section examines generic types.

형식 인수를 제네릭 형식 정의의 형식 매개 변수에 바인딩하여 생성된 형식을 나타내는 Type 개체를 만들 수 있습니다.You can create a Type object that represents a constructed type by binding type arguments to the type parameters of a generic type definition. 두 번째 절차에서 이 방법을 보여 줍니다.The second procedure demonstrates this.

제네릭 형식 및 해당 형식 매개 변수를 검사하려면To examine a generic type and its type parameters

  1. 제네릭 형식을 나타내는 Type 인스턴스를 가져옵니다.Get an instance of Type that represents the generic type. 다음 코드에서는 C# typeof 연산자(Visual Basic에서는 GetType, Visual C++에서는 typeid)를 사용하여 형식을 가져옵니다.In the following code, the type is obtained using the C# typeof operator (GetType in Visual Basic, typeid in Visual C++). Type 개체를 가져오는 다른 방법은 Type 클래스 항목을 참조하세요.See the Type class topic for other ways to get a Type object. 이 절차의 나머지 부분에서는 t라는 메서드 매개 변수에 형식이 포함되어 있습니다.Note that in the rest of this procedure, the type is contained in a method parameter named t.

    Type^ d1 = Dictionary::typeid;
    
    Type d1 = typeof(Dictionary<,>);
    
    Dim d1 As Type = GetType(Dictionary(Of ,))
    
  2. IsGenericType 속성을 사용하여 형식이 제네릭인지 여부를 확인하고, IsGenericTypeDefinition 속성을 사용하여 형식이 제네릭 형식 정의인지 여부를 확인합니다.Use the IsGenericType property to determine whether the type is generic, and use the IsGenericTypeDefinition property to determine whether the type is a generic type definition.

    Console::WriteLine("   Is this a generic type? {0}",
        t->IsGenericType);
    Console::WriteLine("   Is this a generic type definition? {0}",
        t->IsGenericTypeDefinition);
    
    Console.WriteLine("   Is this a generic type? {0}",
        t.IsGenericType);
    Console.WriteLine("   Is this a generic type definition? {0}",
        t.IsGenericTypeDefinition);
    
    Console.WriteLine("   Is this a generic type? " _ 
        & t.IsGenericType)
    Console.WriteLine("   Is this a generic type definition? " _ 
        & t.IsGenericTypeDefinition)
    
  3. GetGenericArguments 메서드를 사용하여 제네릭 형식 인수를 포함하는 배열을 가져옵니다.Get an array that contains the generic type arguments, using the GetGenericArguments method.

    array<Type^>^ typeParameters = t->GetGenericArguments();
    
    Type[] typeParameters = t.GetGenericArguments();
    
    Dim typeParameters() As Type = t.GetGenericArguments()
    
  4. IsGenericParameter 속성을 사용하여 각 형식 인수가 형식 매개 변수인지(예: 제네릭 형식 정의에 있음), 아니면 형식 매개 변수에 대해 지정된 형식인지(예: 생성된 형식에 있음) 확인합니다.For each type argument, determine whether it is a type parameter (for example, in a generic type definition) or a type that has been specified for a type parameter (for example, in a constructed type), using the IsGenericParameter property.

    Console::WriteLine("   List {0} type arguments:",
        typeParameters->Length);
    for each( Type^ tParam in typeParameters )
    {
        if (tParam->IsGenericParameter)
        {
            DisplayGenericParameter(tParam);
        }
        else
        {
            Console::WriteLine("      Type argument: {0}",
                tParam);
        }
    }
    
    Console.WriteLine("   List {0} type arguments:", 
        typeParameters.Length);
    foreach( Type tParam in typeParameters )
    {
        if (tParam.IsGenericParameter)
        {
            DisplayGenericParameter(tParam);
        }
        else
        {
            Console.WriteLine("      Type argument: {0}",
                tParam);
        }
    }
    
    Console.WriteLine("   List {0} type arguments:", _
        typeParameters.Length)
    For Each tParam As Type In typeParameters
        If tParam.IsGenericParameter Then
            DisplayGenericParameter(tParam)
        Else
            Console.WriteLine("      Type argument: {0}", _
                tParam)
        End If
    Next
    
  5. 형식 시스템에서 제네릭 형식 매개 변수는 일반 형식과 마찬가지로 Type 인스턴스로 나타냅니다.In the type system, a generic type parameter is represented by an instance of Type, just as ordinary types are. 다음 코드는 제네릭 형식 매개 변수를 나타내는 Type 개체의 이름 및 매개 변수 위치를 표시합니다.The following code displays the name and parameter position of a Type object that represents a generic type parameter. 매개 변수 위치는 여기서는 중요한 정보가 아니며 다른 제네릭 형식의 형식 인수로 사용된 형식 매개 변수를 검사하는 경우에 더 중요합니다.The parameter position is trivial information here; it is of more interest when you are examining a type parameter that has been used as a type argument of another generic type.

    static void DisplayGenericParameter(Type^ tp)
    {
        Console::WriteLine("      Type parameter: {0} position {1}",
            tp->Name, tp->GenericParameterPosition);
    
    private static void DisplayGenericParameter(Type tp)
    {
        Console.WriteLine("      Type parameter: {0} position {1}", 
            tp.Name, tp.GenericParameterPosition);
    
    Private Shared Sub DisplayGenericParameter(ByVal tp As Type)
        Console.WriteLine("      Type parameter: {0} position {1}", _
            tp.Name, tp.GenericParameterPosition)
    
  6. GetGenericParameterConstraints 메서드를 통해 단일 배열의 모든 제약 조건을 가져와 제네릭 형식 매개 변수의 기본 형식 제약 조건 및 인터페이스 제약 조건을 확인합니다.Determine the base type constraint and the interface constraints of a generic type parameter by using the GetGenericParameterConstraints method to obtain all the constraints in a single array. 제약 조건의 순서는 보장되지 않습니다.Constraints are not guaranteed to be in any particular order.

    Type^ classConstraint = nullptr;
    
    for each(Type^ iConstraint in tp->GetGenericParameterConstraints())
    {
        if (iConstraint->IsInterface)
        {
            Console::WriteLine("         Interface constraint: {0}",
                iConstraint);
        }
    }
    
    if (classConstraint != nullptr)
    {
        Console::WriteLine("         Base type constraint: {0}",
            tp->BaseType);
    }
    else
        Console::WriteLine("         Base type constraint: None");
    
    Type classConstraint = null;
    
    foreach(Type iConstraint in tp.GetGenericParameterConstraints())
    {
        if (iConstraint.IsInterface)
        {
            Console.WriteLine("         Interface constraint: {0}",
                iConstraint);
        }
    }
    
    if (classConstraint != null)
    {
        Console.WriteLine("         Base type constraint: {0}", 
            tp.BaseType);
    }
    else
    {
        Console.WriteLine("         Base type constraint: None");
    }
    
    Dim classConstraint As Type = Nothing
    
    For Each iConstraint As Type In tp.GetGenericParameterConstraints()
        If iConstraint.IsInterface Then
            Console.WriteLine("         Interface constraint: {0}", _
                iConstraint)
        End If
    Next
    
    If classConstraint IsNot Nothing Then
        Console.WriteLine("         Base type constraint: {0}", _
            tp.BaseType)
    Else
        Console.WriteLine("         Base type constraint: None")
    End If
    
  7. GenericParameterAttributes 속성을 사용하여 참조 형식이어야 함 등의 형식 매개 변수에 대한 특수 제약 조건을 검색합니다.Use the GenericParameterAttributes property to discover the special constraints on a type parameter, such as requiring that it be a reference type. 속성에는 다음 코드와 같이 마스킹할 수 있는 차이를 나타내는 값도 포함되어 있습니다.The property also includes values that represent variance, which you can mask off as shown in the following code.

    GenericParameterAttributes sConstraints =
        tp->GenericParameterAttributes &
        GenericParameterAttributes::SpecialConstraintMask;
    
    GenericParameterAttributes sConstraints = 
        tp.GenericParameterAttributes & 
        GenericParameterAttributes.SpecialConstraintMask;
    
    Dim sConstraints As GenericParameterAttributes = _
        tp.GenericParameterAttributes And _
        GenericParameterAttributes.SpecialConstraintMask
    
  8. 특수 제약 조건 특성은 플래그이고, 특수 제약 조건 없음을 나타내는 동일한 플래그(GenericParameterAttributes.None)는 또한 공변성(Covariance) 또는 반공변성(Contravariance) 없음을 나타냅니다.The special constraint attributes are flags, and the same flag (GenericParameterAttributes.None) that represents no special constraints also represents no covariance or contravariance. 따라서 이러한 조건 중 하나를 테스트하려면 적절한 마스크를 사용해야 합니다.Thus, to test for either of these conditions you must use the appropriate mask. 이 경우 GenericParameterAttributes.SpecialConstraintMask을 사용하여 특수 제약 조건 플래그를 격리합니다.In this case, use GenericParameterAttributes.SpecialConstraintMask to isolate the special constraint flags.

    if (sConstraints == GenericParameterAttributes::None)
    {
        Console::WriteLine("         No special constraints.");
    }
    else
    {
        if (GenericParameterAttributes::None != (sConstraints &
            GenericParameterAttributes::DefaultConstructorConstraint))
        {
            Console::WriteLine("         Must have a parameterless constructor.");
        }
        if (GenericParameterAttributes::None != (sConstraints &
            GenericParameterAttributes::ReferenceTypeConstraint))
        {
            Console::WriteLine("         Must be a reference type.");
        }
        if (GenericParameterAttributes::None != (sConstraints &
            GenericParameterAttributes::NotNullableValueTypeConstraint))
        {
            Console::WriteLine("         Must be a non-nullable value type.");
        }
    }
    
    if (sConstraints == GenericParameterAttributes.None)
    {
        Console.WriteLine("         No special constraints.");
    }
    else
    {
        if (GenericParameterAttributes.None != (sConstraints &
            GenericParameterAttributes.DefaultConstructorConstraint))
        {
            Console.WriteLine("         Must have a parameterless constructor.");
        }
        if (GenericParameterAttributes.None != (sConstraints &
            GenericParameterAttributes.ReferenceTypeConstraint))
        {
            Console.WriteLine("         Must be a reference type.");
        }
        if (GenericParameterAttributes.None != (sConstraints &
            GenericParameterAttributes.NotNullableValueTypeConstraint))
        {
            Console.WriteLine("         Must be a non-nullable value type.");
        }
    }
    
    If sConstraints = GenericParameterAttributes.None Then
        Console.WriteLine("         No special constraints.")
    Else
        If GenericParameterAttributes.None <> (sConstraints And _
            GenericParameterAttributes.DefaultConstructorConstraint) Then
            Console.WriteLine("         Must have a parameterless constructor.")
        End If
        If GenericParameterAttributes.None <> (sConstraints And _
            GenericParameterAttributes.ReferenceTypeConstraint) Then
            Console.WriteLine("         Must be a reference type.")
        End If
        If GenericParameterAttributes.None <> (sConstraints And _
            GenericParameterAttributes.NotNullableValueTypeConstraint) Then
            Console.WriteLine("         Must be a non-nullable value type.")
        End If
    End If
    

제네릭 형식 인스턴스 생성Constructing an Instance of a Generic Type

제네릭 형식은 템플릿과 같습니다.A generic type is like a template. 제네릭 형식 매개 변수에 대해 실제 형식을 지정하지 않으면 해당 인스턴스를 만들 수 없습니다.You cannot create instances of it unless you specify real types for its generic type parameters. 런타임에 리플렉션을 사용하여 이 작업을 수행하려면 MakeGenericType 메서드가 필요합니다.To do this at run time, using reflection, requires the MakeGenericType method.

제네릭 형식의 인스턴스를 생성하려면To construct an instance of a generic type

  1. 제네릭 형식을 나타내는 Type 개체를 가져옵니다.Get a Type object that represents the generic type. 다음 코드는 두 가지 방법으로 제네릭 형식 Dictionary<TKey,TValue>를 가져옵니다. 하나는 형식을 설명하는 문자열과 함께 Type.GetType(String) 메서드 오버로드를 사용하는 것이고, 다른 하나는 생성된 형식 Dictionary\<String, Example>(Visual Basic에서는 Dictionary(Of String, Example))에서 GetGenericTypeDefinition 메서드를 호출하는 것입니다.The following code gets the generic type Dictionary<TKey,TValue> in two different ways: by using the Type.GetType(String) method overload with a string describing the type, and by calling the GetGenericTypeDefinition method on the constructed type Dictionary\<String, Example> (Dictionary(Of String, Example) in Visual Basic). MakeGenericType 메서드에는 제네릭 형식 정의가 필요합니다.The MakeGenericType method requires a generic type definition.

    // Use the typeid keyword to create the generic type
    // definition directly.
    Type^ d1 = Dictionary::typeid;
    
    // You can also obtain the generic type definition from a
    // constructed class. In this case, the constructed class
    // is a dictionary of Example objects, with String keys.
    Dictionary<String^, Example^>^ d2 = gcnew Dictionary<String^, Example^>();
    // Get a Type object that represents the constructed type,
    // and from that get the generic type definition. The
    // variables d1 and d4 contain the same type.
    Type^ d3 = d2->GetType();
    Type^ d4 = d3->GetGenericTypeDefinition();
    
    // Use the typeof operator to create the generic type 
    // definition directly. To specify the generic type definition,
    // omit the type arguments but retain the comma that separates
    // them.
    Type d1 = typeof(Dictionary<,>);
    
    // You can also obtain the generic type definition from a
    // constructed class. In this case, the constructed class
    // is a dictionary of Example objects, with String keys.
    Dictionary<string, Example> d2 = new Dictionary<string, Example>();
    // Get a Type object that represents the constructed type,
    // and from that get the generic type definition. The 
    // variables d1 and d4 contain the same type.
    Type d3 = d2.GetType();
    Type d4 = d3.GetGenericTypeDefinition();
    
    ' Use the GetType operator to create the generic type 
    ' definition directly. To specify the generic type definition,
    ' omit the type arguments but retain the comma that separates
    ' them.
    Dim d1 As Type = GetType(Dictionary(Of ,))
    
    ' You can also obtain the generic type definition from a
    ' constructed class. In this case, the constructed class
    ' is a dictionary of Example objects, with String keys.
    Dim d2 As New Dictionary(Of String, Example)
    ' Get a Type object that represents the constructed type,
    ' and from that get the generic type definition. The 
    ' variables d1 and d4 contain the same type.
    Dim d3 As Type = d2.GetType()
    Dim d4 As Type = d3.GetGenericTypeDefinition()
    
  2. 형식 매개 변수를 대체할 형식 인수 배열을 생성합니다.Construct an array of type arguments to substitute for the type parameters. 배열에는 올바른 개수의 Type 개체가 형식 매개 변수 목록에 표시되는 순서대로 포함되어야 합니다.The array must contain the correct number of Type objects, in the same order as they appear in the type parameter list. 이 경우 키(첫 번째 형식 매개 변수)는 String 형식이고, 사전에 있는 값은 Example이라는 클래스 인스턴스입니다.In this case, the key (first type parameter) is of type String, and the values in the dictionary are instances of a class named Example.

    array<Type^>^ typeArgs = {String::typeid, Example::typeid};
    
    Type[] typeArgs = {typeof(string), typeof(Example)};
    
    Dim typeArgs() As Type = _
        { GetType(String), GetType(Example) }
    
  3. MakeGenericType 메서드를 호출하여 형식 인수를 형식 매개 변수에 바인딩하고 형식을 생성합니다.Call the MakeGenericType method to bind the type arguments to the type parameters and construct the type.

    Type^ constructed = d1->MakeGenericType(typeArgs);
    
    Type constructed = d1.MakeGenericType(typeArgs);
    
    Dim constructed As Type = _
        d1.MakeGenericType(typeArgs)
    
  4. CreateInstance(Type) 메서드 오버로드를 사용하여 생성된 형식의 개체를 만듭니다.Use the CreateInstance(Type) method overload to create an object of the constructed type. 다음 코드는 Example 클래스 인스턴스 두 개를 Dictionary<String, Example> 개체에 저장합니다.The following code stores two instances of the Example class in the resulting Dictionary<String, Example> object.

    Object^ o = Activator::CreateInstance(constructed);
    
    object o = Activator.CreateInstance(constructed);
    
    Dim o As Object = Activator.CreateInstance(constructed)
    

예제Example

다음 코드 예제에서는 코드에서 사용된 제네릭 형식 정의 및 생성된 형식을 검사하고 해당 정보를 표시하는 DisplayGenericType 메서드를 정의합니다.The following code example defines a DisplayGenericType method to examine the generic type definitions and constructed types used in the code and display their information. DisplayGenericType 메서드는 IsGenericType, IsGenericParameterGenericParameterPosition 속성과 GetGenericArguments 메서드를 사용하는 방법을 보여 줍니다.The DisplayGenericType method shows how to use the IsGenericType, IsGenericParameter, and GenericParameterPosition properties and the GetGenericArguments method.

또한 이 예제에서는 제네릭 형식 매개 변수를 검사하고 해당 제약 조건을 표시하는 DisplayGenericParameter 메서드를 정의합니다.The example also defines a DisplayGenericParameter method to examine a generic type parameter and display its constraints.

코드 예제에서는 형식 매개 변수 제약 조건을 설명하는 제네릭 형식을 포함하여 테스트 형식 집합을 정의하고 이러한 형식에 대한 정보를 표시하는 방법을 보여 줍니다.The code example defines a set of test types, including a generic type that illustrates type parameter constraints, and shows how to display information about these types.

예제에서는 형식 인수 배열을 만들고 MakeGenericType 메서드를 호출하여 Dictionary<TKey,TValue> 클래스에서 형식을 생성합니다.The example constructs a type from the Dictionary<TKey,TValue> class by creating an array of type arguments and calling the MakeGenericType method. 프로그램은 MakeGenericType을 사용하여 생성된 Type 개체와 typeof(Visual Basic에서는 GetType)를 사용하여 가져온 Type 개체를 비교하여 같음을 보여 줍니다.The program compares the Type object constructed using MakeGenericType with a Type object obtained using typeof (GetType in Visual Basic), demonstrating that they are the same. 마찬가지로, 프로그램은 GetGenericTypeDefinition 메서드를 사용하여 생성된 형식의 제네릭 형식 정의를 가져오고 Dictionary<TKey,TValue> 클래스를 나타내는 Type 개체와 비교합니다.Similarly, the program uses the GetGenericTypeDefinition method to obtain the generic type definition of the constructed type, and compares it to the Type object representing the Dictionary<TKey,TValue> class.

using namespace System;
using namespace System::Reflection;
using namespace System::Collections::Generic;
using namespace System::Security::Permissions;

// Define an example interface.
public interface class ITestArgument {};

// Define an example base class.
public ref class TestBase {};

// Define a generic class with one parameter. The parameter
// has three constraints: It must inherit TestBase, it must
// implement ITestArgument, and it must have a parameterless
// constructor.

generic<class T>
    where T : TestBase, ITestArgument, gcnew()
public ref class Test {};

// Define a class that meets the constraints on the type
// parameter of class Test.
public ref class TestArgument : TestBase, ITestArgument
{
public:
    TestArgument() {}
};

public ref class Example
{
    // The following method displays information about a generic
    // type.
private:
    static void DisplayGenericType(Type^ t)
    {
        Console::WriteLine("\r\n {0}", t);
        Console::WriteLine("   Is this a generic type? {0}",
            t->IsGenericType);
        Console::WriteLine("   Is this a generic type definition? {0}",
            t->IsGenericTypeDefinition);

        // Get the generic type parameters or type arguments.
        array<Type^>^ typeParameters = t->GetGenericArguments();

        Console::WriteLine("   List {0} type arguments:",
            typeParameters->Length);
        for each( Type^ tParam in typeParameters )
        {
            if (tParam->IsGenericParameter)
            {
                DisplayGenericParameter(tParam);
            }
            else
            {
                Console::WriteLine("      Type argument: {0}",
                    tParam);
            }
        }
    }

    // The following method displays information about a generic
    // type parameter. Generic type parameters are represented by
    // instances of System.Type, just like ordinary types.
    static void DisplayGenericParameter(Type^ tp)
    {
        Console::WriteLine("      Type parameter: {0} position {1}",
            tp->Name, tp->GenericParameterPosition);

        Type^ classConstraint = nullptr;

        for each(Type^ iConstraint in tp->GetGenericParameterConstraints())
        {
            if (iConstraint->IsInterface)
            {
                Console::WriteLine("         Interface constraint: {0}",
                    iConstraint);
            }
        }

        if (classConstraint != nullptr)
        {
            Console::WriteLine("         Base type constraint: {0}",
                tp->BaseType);
        }
        else
            Console::WriteLine("         Base type constraint: None");

        GenericParameterAttributes sConstraints =
            tp->GenericParameterAttributes &
            GenericParameterAttributes::SpecialConstraintMask;

        if (sConstraints == GenericParameterAttributes::None)
        {
            Console::WriteLine("         No special constraints.");
        }
        else
        {
            if (GenericParameterAttributes::None != (sConstraints &
                GenericParameterAttributes::DefaultConstructorConstraint))
            {
                Console::WriteLine("         Must have a parameterless constructor.");
            }
            if (GenericParameterAttributes::None != (sConstraints &
                GenericParameterAttributes::ReferenceTypeConstraint))
            {
                Console::WriteLine("         Must be a reference type.");
            }
            if (GenericParameterAttributes::None != (sConstraints &
                GenericParameterAttributes::NotNullableValueTypeConstraint))
            {
                Console::WriteLine("         Must be a non-nullable value type.");
            }
        }
    }

public:
    [PermissionSetAttribute(SecurityAction::Demand, Name="FullTrust")]
    static void Main()
    {
        // Two ways to get a Type object that represents the generic
        // type definition of the Dictionary class.
        //
        // Use the typeid keyword to create the generic type
        // definition directly.
        Type^ d1 = Dictionary::typeid;

        // You can also obtain the generic type definition from a
        // constructed class. In this case, the constructed class
        // is a dictionary of Example objects, with String keys.
        Dictionary<String^, Example^>^ d2 = gcnew Dictionary<String^, Example^>();
        // Get a Type object that represents the constructed type,
        // and from that get the generic type definition. The
        // variables d1 and d4 contain the same type.
        Type^ d3 = d2->GetType();
        Type^ d4 = d3->GetGenericTypeDefinition();

        // Display information for the generic type definition, and
        // for the constructed type Dictionary<String, Example>.
        DisplayGenericType(d1);
        DisplayGenericType(d2->GetType());

        // Construct an array of type arguments to substitute for
        // the type parameters of the generic Dictionary class.
        // The array must contain the correct number of types, in
        // the same order that they appear in the type parameter
        // list of Dictionary. The key (first type parameter)
        // is of type string, and the type to be contained in the
        // dictionary is Example.
        array<Type^>^ typeArgs = {String::typeid, Example::typeid};

        // Construct the type Dictionary<String, Example>.
        Type^ constructed = d1->MakeGenericType(typeArgs);

        DisplayGenericType(constructed);

        Object^ o = Activator::CreateInstance(constructed);

        Console::WriteLine("\r\nCompare types obtained by different methods:");
        Console::WriteLine("   Are the constructed types equal? {0}",
            (d2->GetType()==constructed));
        Console::WriteLine("   Are the generic definitions equal? {0}",
            (d1==constructed->GetGenericTypeDefinition()));

        // Demonstrate the DisplayGenericType and
        // DisplayGenericParameter methods with the Test class
        // defined above. This shows base, interface, and special
        // constraints.
        DisplayGenericType(Test::typeid);
    }
};

int main()
{
    Example::Main();
}
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Security.Permissions;

// Define an example interface.
public interface ITestArgument {}

// Define an example base class.
public class TestBase {}

// Define a generic class with one parameter. The parameter
// has three constraints: It must inherit TestBase, it must
// implement ITestArgument, and it must have a parameterless
// constructor.
public class Test<T> where T : TestBase, ITestArgument, new() {}

// Define a class that meets the constraints on the type
// parameter of class Test.
public class TestArgument : TestBase, ITestArgument
{
    public TestArgument() {}
}

public class Example
{
    // The following method displays information about a generic
    // type.
    private static void DisplayGenericType(Type t)
    {
        Console.WriteLine("\r\n {0}", t);
        Console.WriteLine("   Is this a generic type? {0}",
            t.IsGenericType);
        Console.WriteLine("   Is this a generic type definition? {0}",
            t.IsGenericTypeDefinition);

        // Get the generic type parameters or type arguments.
        Type[] typeParameters = t.GetGenericArguments();

        Console.WriteLine("   List {0} type arguments:", 
            typeParameters.Length);
        foreach( Type tParam in typeParameters )
        {
            if (tParam.IsGenericParameter)
            {
                DisplayGenericParameter(tParam);
            }
            else
            {
                Console.WriteLine("      Type argument: {0}",
                    tParam);
            }
        }
    }

    // The following method displays information about a generic
    // type parameter. Generic type parameters are represented by
    // instances of System.Type, just like ordinary types.
    private static void DisplayGenericParameter(Type tp)
    {
        Console.WriteLine("      Type parameter: {0} position {1}", 
            tp.Name, tp.GenericParameterPosition);

        Type classConstraint = null;

        foreach(Type iConstraint in tp.GetGenericParameterConstraints())
        {
            if (iConstraint.IsInterface)
            {
                Console.WriteLine("         Interface constraint: {0}",
                    iConstraint);
            }
        }

        if (classConstraint != null)
        {
            Console.WriteLine("         Base type constraint: {0}", 
                tp.BaseType);
        }
        else
        {
            Console.WriteLine("         Base type constraint: None");
        }

        GenericParameterAttributes sConstraints = 
            tp.GenericParameterAttributes & 
            GenericParameterAttributes.SpecialConstraintMask;

        if (sConstraints == GenericParameterAttributes.None)
        {
            Console.WriteLine("         No special constraints.");
        }
        else
        {
            if (GenericParameterAttributes.None != (sConstraints &
                GenericParameterAttributes.DefaultConstructorConstraint))
            {
                Console.WriteLine("         Must have a parameterless constructor.");
            }
            if (GenericParameterAttributes.None != (sConstraints &
                GenericParameterAttributes.ReferenceTypeConstraint))
            {
                Console.WriteLine("         Must be a reference type.");
            }
            if (GenericParameterAttributes.None != (sConstraints &
                GenericParameterAttributes.NotNullableValueTypeConstraint))
            {
                Console.WriteLine("         Must be a non-nullable value type.");
            }
        }
    }

    [PermissionSetAttribute(SecurityAction.Demand, Name="FullTrust")]
    public static void Main()
    {
        // Two ways to get a Type object that represents the generic
        // type definition of the Dictionary class. 
        //
        // Use the typeof operator to create the generic type 
        // definition directly. To specify the generic type definition,
        // omit the type arguments but retain the comma that separates
        // them.
        Type d1 = typeof(Dictionary<,>);

        // You can also obtain the generic type definition from a
        // constructed class. In this case, the constructed class
        // is a dictionary of Example objects, with String keys.
        Dictionary<string, Example> d2 = new Dictionary<string, Example>();
        // Get a Type object that represents the constructed type,
        // and from that get the generic type definition. The 
        // variables d1 and d4 contain the same type.
        Type d3 = d2.GetType();
        Type d4 = d3.GetGenericTypeDefinition();

        // Display information for the generic type definition, and
        // for the constructed type Dictionary<String, Example>.
        DisplayGenericType(d1);
        DisplayGenericType(d2.GetType());

        // Construct an array of type arguments to substitute for 
        // the type parameters of the generic Dictionary class.
        // The array must contain the correct number of types, in 
        // the same order that they appear in the type parameter 
        // list of Dictionary. The key (first type parameter)
        // is of type string, and the type to be contained in the
        // dictionary is Example.
        Type[] typeArgs = {typeof(string), typeof(Example)};

        // Construct the type Dictionary<String, Example>.
        Type constructed = d1.MakeGenericType(typeArgs);

        DisplayGenericType(constructed);

        object o = Activator.CreateInstance(constructed);

        Console.WriteLine("\r\nCompare types obtained by different methods:");
        Console.WriteLine("   Are the constructed types equal? {0}",
            (d2.GetType()==constructed));
        Console.WriteLine("   Are the generic definitions equal? {0}",
            (d1==constructed.GetGenericTypeDefinition()));

        // Demonstrate the DisplayGenericType and 
        // DisplayGenericParameter methods with the Test class 
        // defined above. This shows base, interface, and special
        // constraints.
        DisplayGenericType(typeof(Test<>));
    }
}
Imports System.Reflection
Imports System.Collections.Generic
Imports System.Security.Permissions

' Define an example interface.
Public Interface ITestArgument
End Interface

' Define an example base class.
Public Class TestBase
End Class

' Define a generic class with one parameter. The parameter
' has three constraints: It must inherit TestBase, it must
' implement ITestArgument, and it must have a parameterless
' constructor.
Public Class Test(Of T As {TestBase, ITestArgument, New})
End Class

' Define a class that meets the constraints on the type
' parameter of class Test.
Public Class TestArgument
    Inherits TestBase
    Implements ITestArgument
    Public Sub New()
    End Sub
End Class

Public Class Example
    ' The following method displays information about a generic
    ' type.
    Private Shared Sub DisplayGenericType(ByVal t As Type)
        Console.WriteLine(vbCrLf & t.ToString())
        Console.WriteLine("   Is this a generic type? " _ 
            & t.IsGenericType)
        Console.WriteLine("   Is this a generic type definition? " _ 
            & t.IsGenericTypeDefinition)

        ' Get the generic type parameters or type arguments.
        Dim typeParameters() As Type = t.GetGenericArguments()

        Console.WriteLine("   List {0} type arguments:", _
            typeParameters.Length)
        For Each tParam As Type In typeParameters
            If tParam.IsGenericParameter Then
                DisplayGenericParameter(tParam)
            Else
                Console.WriteLine("      Type argument: {0}", _
                    tParam)
            End If
        Next
    End Sub

    ' The following method displays information about a generic
    ' type parameter. Generic type parameters are represented by
    ' instances of System.Type, just like ordinary types.
    Private Shared Sub DisplayGenericParameter(ByVal tp As Type)
        Console.WriteLine("      Type parameter: {0} position {1}", _
            tp.Name, tp.GenericParameterPosition)

        Dim classConstraint As Type = Nothing

        For Each iConstraint As Type In tp.GetGenericParameterConstraints()
            If iConstraint.IsInterface Then
                Console.WriteLine("         Interface constraint: {0}", _
                    iConstraint)
            End If
        Next

        If classConstraint IsNot Nothing Then
            Console.WriteLine("         Base type constraint: {0}", _
                tp.BaseType)
        Else
            Console.WriteLine("         Base type constraint: None")
        End If

        Dim sConstraints As GenericParameterAttributes = _
            tp.GenericParameterAttributes And _
            GenericParameterAttributes.SpecialConstraintMask
        If sConstraints = GenericParameterAttributes.None Then
            Console.WriteLine("         No special constraints.")
        Else
            If GenericParameterAttributes.None <> (sConstraints And _
                GenericParameterAttributes.DefaultConstructorConstraint) Then
                Console.WriteLine("         Must have a parameterless constructor.")
            End If
            If GenericParameterAttributes.None <> (sConstraints And _
                GenericParameterAttributes.ReferenceTypeConstraint) Then
                Console.WriteLine("         Must be a reference type.")
            End If
            If GenericParameterAttributes.None <> (sConstraints And _
                GenericParameterAttributes.NotNullableValueTypeConstraint) Then
                Console.WriteLine("         Must be a non-nullable value type.")
            End If
        End If
    End Sub

    <PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _
    Public Shared Sub Main()
        ' Two ways to get a Type object that represents the generic
        ' type definition of the Dictionary class. 
        '
        ' Use the GetType operator to create the generic type 
        ' definition directly. To specify the generic type definition,
        ' omit the type arguments but retain the comma that separates
        ' them.
        Dim d1 As Type = GetType(Dictionary(Of ,))

        ' You can also obtain the generic type definition from a
        ' constructed class. In this case, the constructed class
        ' is a dictionary of Example objects, with String keys.
        Dim d2 As New Dictionary(Of String, Example)
        ' Get a Type object that represents the constructed type,
        ' and from that get the generic type definition. The 
        ' variables d1 and d4 contain the same type.
        Dim d3 As Type = d2.GetType()
        Dim d4 As Type = d3.GetGenericTypeDefinition()

        ' Display information for the generic type definition, and
        ' for the constructed type Dictionary(Of String, Example).
        DisplayGenericType(d1)
        DisplayGenericType(d2.GetType())

        ' Construct an array of type arguments to substitute for 
        ' the type parameters of the generic Dictionary class.
        ' The array must contain the correct number of types, in 
        ' the same order that they appear in the type parameter 
        ' list of Dictionary. The key (first type parameter)
        ' is of type string, and the type to be contained in the
        ' dictionary is Example.
        Dim typeArgs() As Type = _
            { GetType(String), GetType(Example) }

        ' Construct the type Dictionary(Of String, Example).
        Dim constructed As Type = _
            d1.MakeGenericType(typeArgs)

        DisplayGenericType(constructed)

        Dim o As Object = Activator.CreateInstance(constructed)

        Console.WriteLine(vbCrLf & _
            "Compare types obtained by different methods:")
        Console.WriteLine("   Are the constructed types equal? " _
            & (d2.GetType() Is constructed))
        Console.WriteLine("   Are the generic definitions equal? " _ 
            & (d1 Is constructed.GetGenericTypeDefinition()))

        ' Demonstrate the DisplayGenericType and 
        ' DisplayGenericParameter methods with the Test class 
        ' defined above. This shows base, interface, and special
        ' constraints.
        DisplayGenericType(GetType(Test(Of )))
    End Sub
End Class

참조See also