Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Informationen zu generischen Typen werden auf die gleiche Weise wie Informationen zu anderen Typen abgerufen: durch Untersuchen eines Type Objekts, das den generischen Typ darstellt. Der Hauptunterschied besteht darin, dass ein generischer Typ eine Liste von Type Objekten enthält, die die generischen Typparameter darstellen. Im ersten Verfahren in diesem Abschnitt werden generische Typen untersucht.
Sie können ein Type Objekt erstellen, das einen konstruierten Typ darstellt, indem Sie Typargumente an die Typparameter einer generischen Typdefinition binden. Das zweite Verfahren veranschaulicht dies.
Einen generischen Typ und seine Typparameter untersuchen
Rufen Sie eine Instanz von Type ab, die den generischen Typ repräsentiert. Im folgenden Code wird der Typ mit dem C#
typeof
-Operator (GetType
in Visual Basic) abgerufen. Weitere Möglichkeiten zum Abrufen eines Type Objekts finden Sie unter Type. Im Rest dieser Prozedur ist der Typ in einem Methodenparameter mit dem Namen enthaltent
.Type d1 = typeof(Dictionary<,>);
Dim d1 As Type = GetType(Dictionary(Of ,))
Verwenden Sie die IsGenericType Eigenschaft, um zu bestimmen, ob der Typ generisch ist, und verwenden Sie die IsGenericTypeDefinition Eigenschaft, um zu bestimmen, ob der Typ eine generische Typdefinition ist.
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? " _ & t.IsGenericType) Console.WriteLine(" Is this a generic type definition? " _ & t.IsGenericTypeDefinition)
Rufen Sie ein Array ab, das die generischen Typargumente mit der GetGenericArguments Methode enthält.
Type[] typeParameters = t.GetGenericArguments();
Dim typeParameters() As Type = t.GetGenericArguments()
Bestimmen Sie für jedes Typargument, ob es sich um einen Typparameter (z. B. in einer generischen Typdefinition) oder einen Typ handelt, der für einen Typparameter (z. B. in einem konstruierten Typ) angegeben wurde, mithilfe der IsGenericParameter Eigenschaft.
Console.WriteLine($" List {typeParameters.Length} type arguments:"); foreach (Type tParam in typeParameters) { if (tParam.IsGenericParameter) { DisplayGenericParameter(tParam); } else { Console.WriteLine($" Type argument: {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
Im Typsystem wird ein generischer Typparameter durch eine Instanz von Type, genau wie gewöhnliche Typen dargestellt. Der folgende Code zeigt den Namen und die Parameterposition eines Type Objekts an, das einen generischen Typparameter darstellt. Die Parameterposition ist hier triviale Informationen; es ist interessanter, wenn Sie einen Typparameter untersuchen, der als Typargument eines anderen generischen Typs verwendet wurde.
Console.WriteLine($" Type parameter: {tp.Name} position {tp.GenericParameterPosition}");
Private Shared Sub DisplayGenericParameter(ByVal tp As Type) Console.WriteLine(" Type parameter: {0} position {1}", _ tp.Name, tp.GenericParameterPosition)
Ermitteln Sie die Basistypeinschränkung und die Schnittstelleneinschränkungen eines generischen Typparameters mithilfe der GetGenericParameterConstraints Methode, um alle Einschränkungen in einem einzelnen Array abzurufen. Es wird nicht garantiert, dass Einschränkungen in einer bestimmten Reihenfolge auftreten.
foreach (Type iConstraint in tp.GetGenericParameterConstraints()) { if (iConstraint.IsInterface) { Console.WriteLine($" Interface constraint: {iConstraint}"); } } Console.WriteLine($" Base type constraint: {tp.BaseType ?? tp.BaseType: 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
Verwenden Sie die GenericParameterAttributes Eigenschaft, um die speziellen Einschränkungen für einen Typparameter zu ermitteln, z. B. um einen Verweistyp zu verlangen. Die Eigenschaft enthält auch Werte, die Abweichung darstellen, die Sie wie im folgenden Code dargestellt masken können.
GenericParameterAttributes sConstraints = tp.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
Dim sConstraints As GenericParameterAttributes = _ tp.GenericParameterAttributes And _ GenericParameterAttributes.SpecialConstraintMask
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. Um eine dieser Bedingungen zu testen, müssen Sie daher die entsprechende Maske verwenden. Verwenden Sie GenericParameterAttributes.SpecialConstraintMask in diesem Fall, um die speziellen Einschränkungskennzeichnungen zu isolieren.
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
Erstellen einer Instanz eines generischen Typs
Ein generischer Typ ist wie eine Vorlage. Sie können keine Instanzen davon erstellen, es sei denn, Sie geben echte Typen für die generischen Typparameter an. Wenn Sie dies zur Runtime mit Reflektion machen möchten, ist die MakeGenericType-Methode erforderlich.
Ruft ein Type Objekt ab, das den generischen Typ darstellt. Der folgende Code ruft den generischen Typ Dictionary<TKey,TValue> auf zwei verschiedene Arten ab: mithilfe der Type.GetType(String) Methodenüberladung mit einer Zeichenfolge, die den Typ beschreibt, und durch Aufrufen der GetGenericTypeDefinition Methode für den erstellten Typ
Dictionary\<String, Example>
(Dictionary(Of String, Example)
in Visual Basic). Für die MakeGenericType Methode ist eine generische Typdefinition erforderlich.// 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 = []; // 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()
Erstellen Sie ein Array von Typargumenten, um die Typparameter zu ersetzen. Das Array muss die richtige Anzahl von Type Objekten enthalten, und zwar in der gleichen Reihenfolge wie in der Typparameterliste. In diesem Fall ist der Schlüssel (first type parameter) vom Typ String, und die Werte im Wörterbuch sind Instanzen einer Klasse mit dem Namen
Example
.Type[] typeArgs = [typeof(string), typeof(Example)];
Dim typeArgs() As Type = _ {GetType(String), GetType(Example)}
Rufen Sie die MakeGenericType Methode auf, um die Typargumente an die Typparameter zu binden und den Typ zu erstellen.
Type constructed = d1.MakeGenericType(typeArgs);
Dim constructed As Type = _ d1.MakeGenericType(typeArgs)
Verwenden Sie die CreateInstance(Type) Methodenüberladung, um ein Objekt des erstellten Typs zu erstellen. Der folgende Code speichert zwei Instanzen der
Example
Klasse im resultierendenDictionary<String, Example>
Objekt._ = Activator.CreateInstance(constructed);
Dim o As Object = Activator.CreateInstance(constructed)
Beispiel
Im folgenden Codebeispiel wird eine DisplayGenericType
Methode zum Untersuchen der generischen Typdefinitionen und konstruierten Typen definiert, die im Code verwendet werden, und deren Informationen angezeigt. Die DisplayGenericType
-Methode zeigt, wie die Eigenschaften IsGenericType, IsGenericParameter und GenericParameterPosition sowie die GetGenericArguments-Methode verwendet werden.
Im Beispiel wird außerdem eine DisplayGenericParameter
Methode definiert, mit der ein generischer Typparameter untersucht und die Einschränkungen angezeigt werden.
Das Codebeispiel definiert eine Reihe von Testtypen, einschließlich eines generischen Typs, der Typparametereinschränkungen veranschaulicht, und zeigt, wie Informationen zu diesen Typen angezeigt werden.
Im Beispiel wird ein Typ aus der Dictionary<TKey,TValue> Klasse erstellt, indem ein Array von Typargumenten erstellt und die MakeGenericType Methode aufgerufen wird. Das Programm vergleicht das mit Type konstruierte Objekt mit einem mit MakeGenericType gewonnenen Type-Objekt (typeof
in Visual Basic) und zeigt, dass sie identisch sind. Ebenso verwendet das Programm die GetGenericTypeDefinition Methode, um die generische Typdefinition des konstruierten Typs abzurufen, und vergleicht sie mit dem Objekt, das Type die Dictionary<TKey,TValue> Klasse darstellt.
using System.Reflection;
// 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 {t}");
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.
Type[] typeParameters = t.GetGenericArguments();
Console.WriteLine($" List {typeParameters.Length} type arguments:");
foreach (Type tParam in typeParameters)
{
if (tParam.IsGenericParameter)
{
DisplayGenericParameter(tParam);
}
else
{
Console.WriteLine($" Type argument: {tParam}");
}
}
}
// Displays information about a generic type parameter.
private static void DisplayGenericParameter(Type tp)
{
Console.WriteLine($" Type parameter: {tp.Name} position {tp.GenericParameterPosition}");
foreach (Type iConstraint in tp.GetGenericParameterConstraints())
{
if (iConstraint.IsInterface)
{
Console.WriteLine($" Interface constraint: {iConstraint}");
}
}
Console.WriteLine($" Base type constraint: {tp.BaseType ?? tp.BaseType: 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 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 = [];
// 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);
_ = Activator.CreateInstance(constructed);
Console.WriteLine("\r\nCompare types obtained by different methods:");
Console.WriteLine($" Are the constructed types equal? {d2.GetType() == constructed}");
Console.WriteLine($" Are the generic definitions equal? {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
' 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
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