Gewusst wie: Untersuchen und Instanziieren von generischen Typen mit ReflektionHow to: Examine and Instantiate Generic Types with Reflection

Informationen zu generischen Typen können Sie genauso abrufen wie Informationen zu anderen Typen: indem Sie sich ein Type-Objekt anschauen, das den generischen Typ darstellt.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. Der größte Unterschied besteht dabei darin, dass eine generischer Type eine Liste von Type-Objekten hat, die dessen generischen Typparameter darstellen.The principle difference is that a generic type has a list of Type objects representing its generic type parameters. Die erste Prozedur in diesem Abschnitt beschäftigt sich mit generischen Typen.The first procedure in this section examines generic types.

Sie können ein Type-Objekt erstellen, dass einen konstruierten Typ darstellt, indem Sie Typargumente an die Typparameter einer generischen Typdefinition binden.You can create a Type object that represents a constructed type by binding type arguments to the type parameters of a generic type definition. Dies wird in der zweiten Prozedur veranschaulicht.The second procedure demonstrates this.

So können Sie einen generischen Typ und dessen Typparameter untersuchenTo examine a generic type and its type parameters

  1. Rufen Sie eine Instanz von Type ab, die den generischen Typ darstellt.Get an instance of Type that represents the generic type. Im folgenden Code wird der Typ mit dem typeof-Operator von C# abgerufen (GetType in Visual Basic, typeid in Visual C++).In the following code, the type is obtained using the C# typeof operator (GetType in Visual Basic, typeid in Visual C++). Informationen zu anderen Möglichkeiten zum Abrufen eines Type-Objekts finden Sie im Thema zur Type-Klasse.See the Type class topic for other ways to get a Type object. Beachten Sie, dass der Typ für den Rest der Prozedur im Methodenparameter t enthalten ist.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. Verwenden Sie die IsGenericType-Eigenschaft, um zu bestimmen, ob der Typ generisch ist. Verwenden Sie die IsGenericTypeDefinition-Eigenschaft, um zu bestimmen, ob der Typ eine generische Typdefinition ist.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. Rufen Sie ein Array mit der GetGenericArguments-Methode ab, das die generischen Typargumente enthält.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. Bestimmen Sie mit der IsGenericParameter-Methode für jedes Typargument, ob es sich dabei um einen Typparameter handelt (z.B. in einer generischen Typdefinition) oder um einen Typ, der für einen Typparameter angegeben wurde (z.B. in einem konstruierten Typ).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. Ein generischer Typparameter wird im Typsystem von einer Instanz von Type dargestellt, genauso wie normale Typen.In the type system, a generic type parameter is represented by an instance of Type, just as ordinary types are. In folgendem Code wird der Name und die Parameterposition eines Type-Objekts gezeigt, das einen generischen Typparameter darstellt.The following code displays the name and parameter position of a Type object that represents a generic type parameter. Die Parameterposition ist an dieser Stelle eine unwichtige Information. Sie ist bei der Untersuchung eines Typparameters wichtig, der als Typargument eines anderen generischen Typs verwendet wurde.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. Bestimmen Sie mit der GetGenericParameterConstraints-Methode die Einschränkung des Basistyps und die Schnittstelleneinschränkungen eines generischen Typparameters, um alle Einschränkungen eines einzelnen Arrays zu erhalten.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. Es ist nicht gewährleistet, dass die Einschränkungen in einer bestimmten Reihenfolge angezeigt werden.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. Verwenden Sie die GenericParameterAttributes-Eigenschaft, um die spezielle Einschränkungen eines Typparameters zu erfahren, z.B. die Anforderung, dass es sich dabei um einen Verweistyp handeln muss.Use the GenericParameterAttributes property to discover the special constraints on a type parameter, such as requiring that it be a reference type. Die Eigenschaft enthält außerdem Werte, die Varianz darstellen. Diese können Sie, wie in folgendem Code gezeigt, abtrennen.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. Die Attribute der speziellen Einschränkung sind Flags. Das gleiche Flag (GenericParameterAttributes.None), das keine speziellen Einschränkungen darstellt, steht ebenso für keine Kovarianz oder Kontravarianz.The special constraint attributes are flags, and the same flag (GenericParameterAttributes.None) that represents no special constraints also represents no covariance or contravariance. Deshalb müssen Sie für jede dieser Bedingungen die entsprechende Maske verwenden.Thus, to test for either of these conditions you must use the appropriate mask. Verwenden Sie in diesem Fall GenericParameterAttributes.SpecialConstraintMask, um das Flag für die spezielle Einschränkung zu isolieren.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
    

Konstruieren einer Instanz eines generischen TypsConstructing an Instance of a Generic Type

Ein generischer Typ ähnelt einer Vorlage.A generic type is like a template. Sie können nur dann Instanzen des Typs erstellen, wenn Sie die echten Typen seiner generischen Typparameter angeben.You cannot create instances of it unless you specify real types for its generic type parameters. Wenn Sie dies zur Runtime mit Reflektion machen möchten, ist die MakeGenericType-Methode erforderlich.To do this at run time, using reflection, requires the MakeGenericType method.

So konstruieren Sie eine Instanz eines generischen TypsTo construct an instance of a generic type

  1. Rufen Sie ein Type-Objekt ab, das den generischen Typ darstellt.Get a Type object that represents the generic type. Der folgende Code rufe den generischen Typ Dictionary<TKey,TValue> auf zwei verschiedene Weisen ab: Entweder mit der Type.GetType(String)-Methodenüberladung mit einer Zeichenfolge, die den Typ beschreibt, oder durch Aufrufen der GetGenericTypeDefinition-Methode auf dem konstruierten Typ Dictionary\<String, Example> (Dictionary(Of String, Example) in Visual Basic).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). Die MakeGenericType-Methode erfordert eine generische Typdefinition.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. Konstruieren Sie ein Array aus Typargumenten, um die Typparameter zu ersetzen.Construct an array of type arguments to substitute for the type parameters. Das Array muss die richtige Zahl an Type-Objekten enthalten, und zwar in der gleichen Reihenfolge wie Sie in der Liste der Typparameter auftauchen.The array must contain the correct number of Type objects, in the same order as they appear in the type parameter list. In diesem Fall ist der Schlüssel (der erste Typparameter) vom Typ String, und die Werte im Wörterbuch sind Instanzen der Klasse 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. Rufen Sie die MakeGenericType-Methode auf, um Typargumente an die Typparameter zu binden, und konstruieren Sie den Typ.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. Verwenden Sie die CreateInstance(Type)-Methodenüberladung, um ein Objekt des konstruierten Typs zu erstellen.Use the CreateInstance(Type) method overload to create an object of the constructed type. Der folgende Code speichert zwei Instanzen der Example-Klasse im resultierenden Dictionary<String, Example>-Objekt.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)
    

BeispielExample

In folgendem Codebeispiel wird eine DisplayGenericType-Methode definiert, um die im Code verwendeten generischen Typdefinitionen und konstruierten Typen zu untersuchen und deren Informationen anzuzeigen.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. Die DisplayGenericType-Methode zeigt, wie Sie die Eigenschaften IsGenericType, IsGenericParameter und GenericParameterPosition und die GetGenericArguments-Methode verwenden können.The DisplayGenericType method shows how to use the IsGenericType, IsGenericParameter, and GenericParameterPosition properties and the GetGenericArguments method.

Im Beispiel wird auch eine DisplayGenericParameter-Methode definiert, um einen generischen Typparameter zu untersuchen und dessen Einschränkungen anzuzeigen.The example also defines a DisplayGenericParameter method to examine a generic type parameter and display its constraints.

Im Codebeispiel wird ein Satz von Testtypen definiert, darunter ein generischer Typ, der Typparametereinschränkungen veranschaulicht. Außerdem wird gezeigt, wie Sie Informationen zu diesen Typen anzeigen können.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.

Im Beispiel wird ein Typ aus der Dictionary<TKey,TValue>-Klasse erstellt, indem ein Array von Typargumenten erstellt und die MakeGenericType-Methode aufgerufen wird.The example constructs a type from the Dictionary<TKey,TValue> class by creating an array of type arguments and calling the MakeGenericType method. Das Programm vergleicht das mit MakeGenericType konstruierte Type-Objekt mit einem Type-Objekt, das mit typeof (GetType in Visual Basic) abgerufen wurde. Es wird gezeigt, dass Sie einander entsprechen.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. Gleichermaßen verwendet das Programm die GetGenericTypeDefinition-Methode, um die generische Typdefinition des konstruierten Typs zu erhalten, und vergleicht diese mit dem Type-Objekt, das die Dictionary<TKey,TValue>-Klasse darstellt.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

Siehe auchSee also