다음을 통해 공유


방법: 리플렉션을 사용하여 제네릭 형식 검사 및 인스턴스화

제네릭 형식에 대한 정보는 다른 형식에 대한 정보와 같이, 제네릭 형식을 나타내는 Type 개체를 검사하여 얻습니다. 가장 큰 차이점은 제네릭 형식에는 해당 제네릭 형식 매개 변수를 나타내는 일련의 Type 개체가 있다는 것입니다. 이 단원의 첫 번째 절차에서는 제네릭 형식을 검사합니다.

제네릭 형식 정의의 형식 매개 변수에 형식 인수를 바인딩하여 생성된 형식을 나타내는 Type 개체를 만들 수 있습니다. 두 번째 절차에서는 이 작업에 대해 설명합니다.

제네릭 형식과 해당 형식 매개 변수를 검사하려면

  1. 제네릭 형식을 나타내는 Type의 인스턴스를 가져옵니다. 다음 코드에서는 C# typeof 연산자(Visual Basic의 경우 GetType, Visual C++의 경우 typeid)를 사용하여 형식을 가져옵니다. Type 개체를 가져오는 다른 방법은 Type 클래스 항목을 참조하십시오. 이 절차의 나머지 부분에는 t라는 메서드 매개 변수에 형식이 포함되어 있습니다.

    Dim d1 As Type = GetType(Dictionary(Of ,))
    
    Type d1 = typeof(Dictionary<,>);
    
    Type^ d1 = Dictionary::typeid;
    
  2. 형식이 제네릭인지 여부를 확인하려면 IsGenericType 속성을 사용하고 형식이 제네릭 형식 정의인지 여부를 확인하려면 IsGenericTypeDefinition 속성을 사용합니다.

    Console.WriteLine("   Is this a generic type? " _ 
        & t.IsGenericType)
    Console.WriteLine("   Is this a generic type definition? " _ 
        & 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? {0}",
        t->IsGenericType);
    Console::WriteLine("   Is this a generic type definition? {0}",
        t->IsGenericTypeDefinition);
    
  3. GetGenericArguments 메서드를 사용하여 제네릭 형식 인수가 포함된 배열을 가져옵니다.

    Dim typeParameters() As Type = t.GetGenericArguments()
    
    Type[] typeParameters = t.GetGenericArguments();
    
    array<Type^>^ typeParameters = t->GetGenericArguments();
    
  4. 각 형식 인수에 대해 IsGenericParameter 속성을 사용하여 해당 인수가 형식 매개 변수(예를 들어, 제네릭 형식 정의에 있음)인지 또는 형식 매개 변수에 대해 지정된 형식(예를 들어, 생성된 형식에 있음)인지 여부를 확인합니다.

    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
    
    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( Type^ tParam in typeParameters )
    {
        if (tParam->IsGenericParameter)
        {
            DisplayGenericParameter(tParam);
        }
        else
        {
            Console::WriteLine("      Type argument: {0}",
                tParam);
        }
    }
    
  5. 형식 시스템의 경우 제네릭 형식 매개 변수는 일반 형식과 같이 Type의 인스턴스로 표시됩니다. 다음 코드에서는 제네릭 형식 매개 변수를 나타내는 Type 개체의 이름과 매개 변수 위치를 표시합니다. 매개 변수 위치는 여기에서는 그다지 중요하지 않지만 다른 제네릭 형식의 형식 인수로 사용된 형식 매개 변수를 검사할 때 보다 중요합니다.

    Private Shared Sub DisplayGenericParameter(ByVal tp As Type)
        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);
    
    static void DisplayGenericParameter(Type^ tp)
    {
        Console::WriteLine("      Type parameter: {0} position {1}",
            tp->Name, tp->GenericParameterPosition);
    
  6. GetGenericParameterConstraints 메서드를 사용하여 단일 배열의 모든 제약 조건을 가져옴으로써 제네릭 형식 매개 변수의 기본 형식 제약 조건과 인터페이스 제약 조건을 확인합니다. 제약 조건의 순서는 특별히 정해져 있지 않습니다.

    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
    
    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"); 
    
    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");
    
  7. 형식 매개 변수가 참조 형식이어야 하는 것과 같이 형식 매개 변수에 대한 특수 제약 조건을 확인하려면 GenericParameterAttributes 속성을 사용합니다. 이 속성에는 다음 코드와 같이 가릴 수 있는 가변성을 나타내는 값도 포함되어 있습니다.

    Dim sConstraints As GenericParameterAttributes = _
        tp.GenericParameterAttributes And _
        GenericParameterAttributes.SpecialConstraintMask
    
    GenericParameterAttributes sConstraints = 
        tp.GenericParameterAttributes & 
        GenericParameterAttributes.SpecialConstraintMask;
    
    GenericParameterAttributes sConstraints =
        tp->GenericParameterAttributes &
        GenericParameterAttributes::SpecialConstraintMask;
    
  8. 특수 제약 조건 특성은 플래그이며 특수 제약 조건이 없음을 나타내는 동일한 플래그(GenericParameterAttributes.None)도 공 분산 또는 반공변성(Contravariance)을 나타냅니다. 그러므로 이러한 조건 중 어느 하나를 테스트하려면 적절한 마스크를 사용해야 합니다. 이 경우에는 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
    
    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.");
        }
    }
    

제네릭 형식의 인스턴스 생성

제네릭 형식은 템플릿과 같습니다. 해당 제네릭 형식 매개 변수의 실제 형식을 지정해야 해당 인스턴스를 만들 수 있습니다. 런타임에 리플렉션을 사용하여 이 작업을 수행하려면 MakeGenericType 메서드가 필요합니다.

제네릭 형식의 인스턴스를 생성하려면

  1. 제네릭 형식을 나타내는 Type 개체를 가져옵니다. 다음 코드에서는 두 가지 다른 방법으로 Dictionary<TKey, TValue> 제네릭 형식을 가져옵니다. 즉, 형식에 대해 설명하는 문자열에 Type.GetType(String) 메서드 오버로드를 사용하거나, 생성된 형식 Dictionary<String, Example>(Visual Basic의 경우 Dictionary(Of String, Example))에 대해 GetGenericTypeDefinition 메서드를 호출합니다. MakeGenericType 메서드에는 제네릭 형식 정의가 필요합니다.

    ' 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()
    
    // 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 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();
    
  2. 형식 매개 변수를 대체할 형식 인수 배열을 생성합니다. 이 배열에는 올바른 수의 Type 개체가 포함되어야 하며 개체 순서는 형식 매개 변수 목록에 표시되는 순서와 동일해야 합니다. 이 경우 첫 번째 형식 매개 변수인 키의 형식은 String이며 사전의 값은 Example 클래스의 인스턴스입니다.

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

    Dim constructed As Type = _
        d1.MakeGenericType(typeArgs)
    
    Type constructed = d1.MakeGenericType(typeArgs);
    
    Type^ constructed = d1->MakeGenericType(typeArgs);
    
  4. 생성된 형식의 개체를 만들려면 CreateInstance(Type) 메서드 오버로드를 사용합니다. 다음 코드에서는 결과 Dictionary<String, Example> 개체에 Example 클래스의 두 인스턴스를 저장합니다.

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

예제

다음 코드 예제에서는 DisplayGenericType 메서드를 정의하여 코드에서 사용되는 제네릭 형식 정의와 생성된 형식을 검사하고 해당 정보를 표시합니다. DisplayGenericType 메서드는 IsGenericType, IsGenericParameterGenericParameterPosition 속성과 GetGenericArguments 메서드를 사용하는 방법을 보여 줍니다.

이 예제에서는 또한 DisplayGenericParameter 메서드를 정의하여 제네릭 형식 매개 변수를 검사하고 해당 제약 조건을 표시합니다.

이 코드 예제에서는 형식 매개 변수의 제약 조건을 설명하는 제네릭 형식을 포함하여 일련의 테스트 형식을 정의하며 해당 형식에 대한 정보를 표시하는 방법을 보여 줍니다.

또한 형식 인수의 배열을 만들고 MakeGenericType 메서드를 호출하여 Dictionary<TKey, TValue> 클래스에서 형식을 생성합니다. 이 프로그램은 MakeGenericType을 사용하여 생성된 Type 개체와 typeof(Visual Basic의 경우 GetType)를 사용하여 가져온 Type 개체를 비교하여 동일한 개체임을 보여 줍니다. 또한 이와 유사하게 GetGenericTypeDefinition 메서드를 사용하여 생성된 형식의 제네릭 형식 정의를 가져오고 해당 정의와 Dictionary<TKey, TValue> 클래스를 나타내는 Type 개체를 비교합니다.

Imports System
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
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<>));
    }
}
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();
}

코드 컴파일

  • 이 코드에는 컴파일에 필요한 C# using 문(Visual Basic의 경우 Imports)이 포함되어 있습니다.

  • 추가 어셈블리 참조는 필요하지 않습니다.

  • csc.exe, vbc.exe 또는 cl.exe를 사용하여 명령줄에서 코드를 컴파일합니다. Visual Studio에서 코드를 컴파일하려면 콘솔 응용 프로젝트 템플릿에 코드를 삽입합니다.

참고 항목

참조

Type

MethodInfo

개념

리플렉션 및 제네릭 형식

형식 정보 보기

.NET Framework의 제네릭