Type.MakeGenericType(Type[]) Methode

Definition

Ersetzt die Typparameter der aktuellen generischen Typdefinition durch die Elemente eines Arrays von Typen und gibt ein Type-Objekt zurück, das den resultierenden konstruierten Typ darstellt.

public:
 abstract Type ^ MakeGenericType(... cli::array <Type ^> ^ typeArguments);
public:
 virtual Type ^ MakeGenericType(... cli::array <Type ^> ^ typeArguments);
public abstract Type MakeGenericType (params Type[] typeArguments);
public virtual Type MakeGenericType (params Type[] typeArguments);
abstract member MakeGenericType : Type[] -> Type
abstract member MakeGenericType : Type[] -> Type
override this.MakeGenericType : Type[] -> Type
Public MustOverride Function MakeGenericType (ParamArray typeArguments As Type()) As Type
Public Overridable Function MakeGenericType (ParamArray typeArguments As Type()) As Type

Parameter

typeArguments
Type[]

Ein Array von Typen, die die Typparameter des aktuellen generischen Typs ersetzen sollen.

Gibt zurück

Type

Ein Type, der den konstruierten Typ darstellt, der durch Ersetzen der Typparameter des aktuellen generischen Typs durch die Elemente von typeArguments erstellt wurde.

Ausnahmen

Der aktuelle Typ stellt keine generische Typdefinition dar. Das heißt, IsGenericTypeDefinition gibt false zurück.

typeArguments ist null.

- oder - Ein beliebiges Element von typeArguments ist null.

Die Anzahl der Elemente im typeArguments entspricht nicht der Anzahl von Typparametern in der aktuellen generischen Typdefinition.

- oder - Ein beliebiges Element von typeArguments erfüllt nicht die Einschränkungen, die für den entsprechenden Typparameter des aktuellen generischen Typs angegeben wurden.

- oder - typeArguments enthält ein Element, das ein Zeigertyp (IsPointer gibt true zurück), vom Typ „by-ref“ (IsByRef gibt true zurück) oder Void ist.

Die aufgerufene Methode wird in der Basisklasse nicht unterstützt. Abgeleitete Klassen müssen eine Implementation angeben.

Beispiele

Im folgenden Beispiel wird die MakeGenericType Methode verwendet, um einen konstruierten Typ aus der generischen Typdefinition für den Dictionary<TKey,TValue> Typ zu erstellen. Der konstruierte Typ stellt eine Dictionary<TKey,TValue> Von Test Objekten mit Zeichenfolgentasten dar.

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

namespace Example
{
    public ref class Test
    {
    public:
        static void CreateConstructedType(void)
        {      
            Console::WriteLine("\r\n--- Create a constructed type"
                " from the generic Dictionary`2 type.");
            
            // Create a type object representing 
            // the generic Dictionary`2 type.
            Type^ genericType = Type::GetType(
                "System.Collections.Generic.Dictionary`2");
            if (genericType != nullptr)
            {  
                DisplayTypeInfo(genericType);
            }
            else
            {
                Console::WriteLine("The type is not found");
                return;
            }
            
            // Create an array of types to substitute for the type
            // parameters of Dictionary`2. 
            // The key is of type string, and the type to be 
            // contained in the Dictionary`2 is Test.
            array<Type^>^ typeArgs = {String::typeid, Test::typeid};
            Type^ constructedType = 
                genericType->MakeGenericType(typeArgs);
            DisplayTypeInfo(constructedType);
            
            // Compare the type objects obtained above to type objects
            // obtained using typeof() and GetGenericTypeDefinition().
            Console::WriteLine("\r\n--- Compare types obtained by"
                " different methods:");

            Type^ definedType = Dictionary<String^, Test^>::typeid;
            Console::WriteLine("\tAre the constructed types "
                "equal? {0}", definedType == constructedType);
            Console::WriteLine("\tAre the generic types equal? {0}", 
                definedType->GetGenericTypeDefinition() == genericType);
        }

    private:
        static void DisplayTypeInfo(Type^ typeToDisplay)
        {   
            Console::WriteLine("\r\n{0}", typeToDisplay);
            Console::WriteLine("\tIs this a generic type definition? "
                "{0}", typeToDisplay->IsGenericTypeDefinition);
            Console::WriteLine("\tIs it a generic type? "
                "{0}", typeToDisplay->IsGenericType);
            
            array<Type^>^ typeArguments = 
                typeToDisplay->GetGenericArguments();
            Console::WriteLine("\tList type arguments ({0}):", 
                typeArguments->Length);
            
            for each (Type^ typeArgument in typeArguments)
            {   
                Console::WriteLine("\t\t{0}", typeArgument);
            }
        }
    };
}

int main(void)
{
    Example::Test::CreateConstructedType();
}

/* This example produces the following output:

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

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

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

--- Compare types obtained by different methods:
          Are the constructed types equal? True
          Are the generic types equal? True
 */
using System;
using System.Reflection;
using System.Collections.Generic;

public class Test
{
    public static void Main()
    {
        Console.WriteLine("\r\n--- Create a constructed type from the generic Dictionary type.");

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

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

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

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

        Type t = typeof(Dictionary<String, Test>);
        Console.WriteLine("\tAre the constructed types equal? {0}", t == constructed);
        Console.WriteLine("\tAre the generic types equal? {0}", 
            t.GetGenericTypeDefinition() == generic);
    }

    private static void DisplayTypeInfo(Type t)
    {
        Console.WriteLine("\r\n{0}", t);

        Console.WriteLine("\tIs this a generic type definition? {0}", 
            t.IsGenericTypeDefinition);

        Console.WriteLine("\tIs it a generic type? {0}", 
            t.IsGenericType);

        Type[] typeArguments = t.GetGenericArguments();
        Console.WriteLine("\tList type arguments ({0}):", typeArguments.Length);
        foreach (Type tParam in typeArguments)
        {
            Console.WriteLine("\t\t{0}", tParam);
        }
    }
}

/* This example produces the following output:

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

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

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

--- Compare types obtained by different methods:
        Are the constructed types equal? True
        Are the generic types equal? True
 */
open System
open System.Collections.Generic

type Test() = class end

let displayTypeInfo (t: Type) =
    printfn $"\r\n{t}"

    printfn $"\tIs this a generic type definition? {t.IsGenericTypeDefinition}" 

    printfn $"\tIs it a generic type? {t.IsGenericType}"

    let typeArguments = t.GetGenericArguments()
    printfn $"\tList type arguments ({typeArguments.Length}):"
    for tParam in typeArguments do
        printfn $"\t\t{tParam}"

printfn "\r\n--- Create a constructed type from the generic Dictionary type."

// Create a type object representing the generic Dictionary 
// type, by calling .GetGenericTypeDefinition().
let generic = typeof<Dictionary<_,_>>.GetGenericTypeDefinition()
displayTypeInfo generic

// Create an array of types to substitute for the type
// parameters of Dictionary. The key is of type string, and
// the type to be contained in the Dictionary is Test.
let typeArgs = [| typeof<string>; typeof<Test> |]

// Create a Type object representing the constructed generic type.
let constructed = generic.MakeGenericType typeArgs
displayTypeInfo constructed

(* This example produces the following output:

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

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

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

Public Class Test
    Public Shared Sub Main()
        Console.WriteLine(vbCrLf & "--- Create a constructed type from the generic Dictionary type.")

        ' Create a type object representing the generic Dictionary 
        ' type, by omitting the type arguments (but keeping the 
        ' comma that separates them, so the compiler can infer the
        ' number of type parameters).
        Dim generic As Type = GetType(Dictionary(Of ,))
        DisplayTypeInfo(generic)

        ' Create an array of types to substitute for the type
        ' parameters of Dictionary. The key is of type string, and
        ' the type to be contained in the Dictionary is Test.
        Dim typeArgs() As Type = { GetType(String), GetType(Test) }

        ' Create a Type object representing the constructed generic
        ' type.
        Dim constructed As Type = generic.MakeGenericType(typeArgs)
        DisplayTypeInfo(constructed)

        ' Compare the type objects obtained above to type objects
        ' obtained using GetType() and GetGenericTypeDefinition().
        Console.WriteLine(vbCrLf & "--- Compare types obtained by different methods:")

        Dim t As Type = GetType(Dictionary(Of String, Test))
        Console.WriteLine(vbTab & "Are the constructed types equal? " _
            & (t Is constructed))
        Console.WriteLine(vbTab & "Are the generic types equal? " _ 
            & (t.GetGenericTypeDefinition() Is generic))
    End Sub

    Private Shared Sub DisplayTypeInfo(ByVal t As Type)
        Console.WriteLine(vbCrLf & t.ToString())

        Console.WriteLine(vbTab & "Is this a generic type definition? " _ 
            & t.IsGenericTypeDefinition)

        Console.WriteLine(vbTab & "Is it a generic type? " _ 
            & t.IsGenericType)

        Dim typeArguments() As Type = t.GetGenericArguments()
        Console.WriteLine(vbTab & "List type arguments ({0}):", _
            typeArguments.Length)
        For Each tParam As Type In typeArguments       
            Console.WriteLine(vbTab & vbTab & tParam.ToString())
        Next
    End Sub
End Class

' This example produces the following output:
'
'--- Create a constructed type from the generic Dictionary type.
'
'System.Collections.Generic.Dictionary'2[TKey,TValue]
'        Is this a generic type definition? True
'        Is it a generic type? True
'        List type arguments (2):
'                TKey
'                TValue
'
'System.Collections.Generic.Dictionary`2[System.String,Test]
'        Is this a generic type definition? False
'        Is it a generic type? True
'        List type arguments (2):
'                System.String
'                Test
'
'--- Compare types obtained by different methods:
'        Are the constructed types equal? True
'        Are the generic types equal? True

Hinweise

Mit der MakeGenericType Methode können Sie Code schreiben, der bestimmten Typen den Typparametern einer generischen Typdefinition zuweist und somit ein Type Objekt erstellt, das einen bestimmten konstruierten Typ darstellt. Sie können dieses Type Objekt verwenden, um Laufzeitinstanzen des erstellten Typs zu erstellen.

Typen, die mit MakeGenericType geöffnet werden, können also einige ihrer Typargumente Typparameter sein, um generische Methoden oder Typen einzuschließen. Sie können solche geöffneten konstruierten Typen verwenden, wenn Sie dynamische Assemblys ausgeben. Ziehen Sie beispielsweise die Klassen Base und Derived im folgenden Code in Betracht.

generic<typename T, typename U>
    public ref class Base { };
generic<typename V>
    public ref class Derived : Base<int, V> { };
public class Base<T, U> { }
public class Derived<V> : Base<int, V> { }
type Base<'T, 'U>() = class end
type Derived<'V>() = inherit Base<int, 'V>()
Public Class Base(Of T, U)
End Class
Public Class Derived(Of V)
    Inherits Base(Of Integer, V)
End Class

Um in einer dynamischen Assembly zu generieren Derived , ist es erforderlich, seinen Basistyp zu erstellen. Rufen Sie dazu die MakeGenericType Methode für ein Type Objekt auf, das die Klasse Basedarstellt, mithilfe der generischen Typargumente Int32 und des Typparameters V von Derived. Da Typen und generische Typparameter sowohl durch Type Objekte dargestellt werden, kann ein Array, das beide enthält, an die MakeGenericType Methode übergeben werden.

Hinweis

Ein konstruierter Typ wie Base<int, V> z. B. ist nützlich, wenn Code emittiert wird, aber Sie können die MakeGenericType Methode für diesen Typ nicht aufrufen, da es sich nicht um eine generische Typdefinition handelt. Um einen geschlossenen konstruierten Typ zu erstellen, der instanziiert werden kann, rufen Sie zuerst die GetGenericTypeDefinition Methode auf, um ein Type Objekt abzurufen, das die generische Typdefinition darstellt, und rufen Sie dann mit den gewünschten Typargumenten auf MakeGenericType .

Das Type zurückgegebene MakeGenericType Objekt entspricht dem Type Abrufen der GetType Methode des resultierenden konstruierten Typs oder der Methode eines konstruierten Typs, das GetType aus derselben generischen Typdefinition mithilfe der gleichen Typargumente erstellt wurde.

Hinweis

Ein Array generischer Typen ist kein generischer Typ. Sie können keinen Arraytyp C<T>[] wie (Dim ac() As C(Of T) in Visual Basic) aufrufenMakeGenericType. Um einen geschlossenen generischen Typ aus C<T>[]zu erstellen, rufen Sie aufGetElementType, um die generische Typdefinition abzurufen; rufen Sie MakeGenericType die generische Typdefinition C<T>auf, um den konstruierten Typ zu erstellen; und rufen Sie schließlich die MakeArrayType Methode für den konstruierten Typ auf, um den Arraytyp zu erstellen. Dasselbe gilt für Zeigertypen und ref -typen (ByRef in Visual Basic).

Eine Liste der invarianten Bedingungen für Begriffe, für Begriffe, die für die Reflektion mit generischen Methoden verwendet werden, finden Sie in den Hinweisen zur Eigenschaft IsGenericType.

Geschachtelte Typen

Wenn ein generischer Typ mithilfe von C#, C++ oder Visual Basic definiert wird, sind die geschachtelten Typen alle generisch. Dies gilt auch dann, wenn die geschachtelten Typen keine eigenen Typparameter haben, da alle drei Sprachen die Typparameter der Typparameter in die Typparameterlisten geschachtelter Typen einschließen. Berücksichtigen Sie die folgenden Klassen:

generic<typename T> public ref class Outermost
{
public:
    generic<typename U> ref class Inner
    {
    public:
        generic<typename V> ref class Innermost1 {};
        ref class Innermost2 {};
    };
};
public class Outermost<T>
{
    public class Inner<U>
    {
        public class Innermost1<V> {}
        public class Innermost2 {}
    }
}
Public Class Outermost(Of T)
    Public Class Inner(Of U)
        Public Class Innermost1(Of V)
        End Class
        Public Class Innermost2
        End Class
    End Class
End Class

Die Typparameterliste der geschachtelten Klasse Inner weist zwei Typparameter auf, T und Udie erste ist der Typparameter der eingeschlossenen Klasse. Ebenso verfügt die Typparameterliste der geschachtelten Klasse Innermost1 über drei Typparameter, T``U, und V, mit T und U aus den eingeschlossenen Klassen. Die geschachtelte Klasse Innermost2 verfügt über zwei Typparameter und T U, die aus ihren eingeschlossenen Klassen stammen.

Wenn die Parameterliste des eingeschlossenen Typs mehr als einen Typparameter aufweist, sind alle Typparameter in der Typparameterliste des geschachtelten Typs enthalten.

Um einen generischen Typ aus der generischen Typdefinition für einen geschachtelten Typ zu erstellen, rufen Sie die MakeGenericType Methode mit dem Array auf, das durch Verketten der Typargumentarrays aller eingeschlossenen Typen gebildet wird, beginnend mit dem äußerst generischen Typ, und enden Sie mit dem Typargumentarray des geschachtelten Typs selbst, wenn sie Typparameter selbst enthält. Um eine Instanz von Innermost1, rufen Sie die MakeGenericType Methode mit einem Array mit drei Typen auf, die T, U und V zugewiesen werden sollen. Um eine Instanz von Innermost2, rufen Sie die MakeGenericType Methode mit einem Array mit zwei Typen auf, die T und U zugewiesen werden sollen.

Die Sprachen verteilen die Typparameter von Eingeschlossenen Typen in dieser Weise, sodass Sie die Typparameter eines eingeschlossenen Typs verwenden können, um Felder von geschachtelten Typen zu definieren. Andernfalls würden die Typparameter nicht in den Textkörpern der geschachtelten Typen enthalten sein. Es ist möglich, geschachtelte Typen zu definieren, ohne die Typparameter der eingeschlossenen Typen zu verteilen, indem Code in dynamischen Assemblys oder mithilfe der Ilasm.exe (IL Assembler) zurückgegeben wird. Berücksichtigen Sie den folgenden Code für die MSIL-Assembler:

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

In diesem Beispiel ist es nicht möglich, ein Feld vom Typ T oder U in der Klasse Innermostzu definieren, da diese Typparameter nicht im Bereich sind. Der folgende Assemblercode definiert geschachtelte Klassen, die sich verhalten, wie sie in C++, Visual Basic und C# definiert werden:

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

Sie können die Ildasm.exe (IL Disassembler) verwenden, um geschachtelte Klassen zu untersuchen, die in den Sprachen auf hoher Ebene definiert sind, und dieses Benennungsschema beobachten.

Gilt für:

Siehe auch