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.
Aus Sicht der Reflexion besteht der Unterschied zwischen einem generischen Typ und einem normalen Typ darin, dass ein generischer Typ einem Satz von Typparametern (wenn es sich um eine generische Typdefinition handelt) oder Typargumente (wenn es sich um einen konstruierten Typ handelt) zugeordnet hat. Eine generische Methode unterscheidet sich von einer gewöhnlichen Methode auf die gleiche Weise.
Es gibt zwei Schlüssel, um zu verstehen, wie Spiegelung generische Typen und Methoden behandelt:
Die Typparameter generischer Typdefinitionen und generische Methodendefinitionen werden durch Instanzen der Type Klasse dargestellt.
Hinweis
Viele Eigenschaften und Methoden von Type zeigen ein anderes Verhalten, wenn ein Type-Objekt einen generischen Typparameter darstellt. Diese Unterschiede sind in den Artikeln zu Eigenschaften und Methoden dokumentiert. Beispiel: siehe IsAutoClass und DeclaringType. Darüber hinaus sind einige Elemente nur gültig, wenn ein Type Objekt einen generischen Typparameter darstellt. Siehe zum Beispiel GetGenericTypeDefinition.
Wenn eine Instanz eines Type generischen Typs darstellt, enthält sie ein Array von Typen, die die Typparameter (für generische Typdefinitionen) oder die Typargumente (für konstruierte Typen) darstellen. Dasselbe gilt für eine Instanz der MethodInfo Klasse, die eine generische Methode darstellt.
Reflection stellt Methoden zur Verfügung, die es Ihnen über Type und MethodInfo ermöglichen, auf das Array von Typparametern zuzugreifen und zu bestimmen, ob eine Instanz von Type einen Typparameter oder einen tatsächlichen Typ darstellt.
Beispielcode zur Veranschaulichung der hier beschriebenen Methoden finden Sie unter How to: Examine and Instantiate Generic Types with Reflection.
In der folgenden Diskussion wird davon ausgegangen, dass sie mit der Terminologie von Generika vertraut sind, z. B. den Unterschied zwischen Typparametern und Argumenten und offenen oder geschlossenen konstruierten Typen. Weitere Informationen finden Sie unter Generics.
Ist dies ein generischer Typ oder eine generische Methode?
Wenn Sie spiegelung verwenden, um einen unbekannten Typ zu untersuchen, dargestellt durch eine Instanz von Type, verwenden Sie die IsGenericType Eigenschaft, um zu bestimmen, ob der unbekannte Typ generisch ist. Er gibt zurück true
, wenn der Typ generisch ist. Wenn Sie eine unbekannte Methode untersuchen, die durch eine Instanz der MethodInfo Klasse dargestellt wird, verwenden Sie die IsGenericMethod Eigenschaft, um zu bestimmen, ob die Methode generisch ist.
Ist dies eine generische Typ- oder Methodendefinition?
Verwenden Sie die IsGenericTypeDefinition Eigenschaft, um zu bestimmen, ob ein Type Objekt eine generische Typdefinition darstellt, und verwenden Sie die IsGenericMethodDefinition Methode, um zu bestimmen, ob eine MethodInfo generische Methodendefinition darstellt.
Generische Typ- und Methodendefinitionen sind die Vorlagen, aus denen instanziierbare Typen erstellt werden. Generische Typen in den .NET-Bibliotheken, wie z. B. Dictionary<TKey,TValue>, sind generische Typdefinitionen.
Ist der Typ oder die Methode offen oder geschlossen?
Ein generischer Typ oder eine methode wird geschlossen, wenn instanziierbare Typen durch alle Typparameter ersetzt wurden, einschließlich aller Typparameter aller eingeschlossenen Typen. Sie können nur eine Instanz eines generischen Typs erstellen, wenn sie geschlossen ist. Die Type.ContainsGenericParameters Eigenschaft gibt zurück true
, wenn ein Typ geöffnet ist. Bei Methoden führt die MethodBase.ContainsGenericParameters Methode dieselbe Funktion aus.
Generieren geschlossener generischer Typen
Nachdem Sie über einen generischen Typ oder eine Methodendefinition verfügen, verwenden Sie die MakeGenericType Methode, um einen geschlossenen generischen Typ oder die MakeGenericMethod Methode zu erstellen, um eine MethodInfo für eine geschlossene generische Methode zu erstellen.
Abrufen der generischen Typ- oder Methodendefinition
Wenn Sie über einen offenen generischen Typ oder eine Methode verfügen, die keine generische Typ- oder Methodendefinition ist, können Sie keine Instanzen davon erstellen und die fehlenden Typparameter nicht angeben. Sie müssen über eine generische Typ- oder Methodendefinition verfügen. Verwenden Sie die GetGenericTypeDefinition Methode, um die generische Typdefinition oder die GetGenericMethodDefinition Methode abzurufen, um die generische Methodendefinition abzurufen.
Wenn Sie z. B. ein Type Objekt für Dictionary<int, string>
haben und den Typ Dictionary<string, MyClass>
erstellen möchten, können Sie mit der GetGenericTypeDefinition Methode ein Type Objekt für Dictionary<TKey, TValue>
abrufen und dann die MakeGenericType Methode verwenden, um ein Type Objekt für Dictionary<int, MyClass>
zu erzeugen.
Ein Beispiel für einen offenen generischen Typ, der kein generischer Typ ist, finden Sie unter Type-Parameter oder Typargument.
Überprüfen von Typargumenten und Typparametern
Verwenden Sie die Type.GetGenericArguments Methode, um ein Array von Type Objekten abzurufen, die die Typparameter oder Typargumente eines generischen Typs darstellen, und verwenden Sie die MethodInfo.GetGenericArguments Methode, um die gleiche Für eine generische Methode zu tun.
Sobald Sie wissen, dass ein Type Objekt einen Typparameter darstellt, gibt es viele zusätzliche Fragen, die die Reflexion beantworten kann. Sie können die Quelle des Typparameters, die Position und die Einschränkungen des Typparameters ermitteln.
Typparameter oder Typargument
Um festzustellen, ob ein bestimmtes Element des Arrays ein Typparameter oder ein Typargument ist, verwenden Sie die IsGenericParameter Eigenschaft. Die IsGenericParameter Eigenschaft ist true
, wenn das Element ein Typparameter ist.
Ein generischer Typ kann geöffnet werden, ohne eine generische Typdefinition zu sein, in diesem Fall enthält er eine Mischung aus Typargumenten und Typparametern. Im folgenden Code wird die Klasse D
beispielsweise von einem Typ abgeleitet, der durch das Ersetzen des ersten Typparameters von D
mit dem zweiten Typparameter von B
erstellt wird.
class B<T, U> {}
class D<V, W> : B<int, V> {}
Class B(Of T, U)
End Class
Class D(Of V, W)
Inherits B(Of Integer, V)
End Class
Wenn Sie ein Type-Objekt abrufen, das D<V, W>
repräsentiert, und die BaseType-Eigenschaft verwenden, um dessen Basistyp zu erhalten, ist der resultierende type B<int, V>
offen, es handelt sich jedoch nicht um eine generische Typdefinition.
Quelle eines generischen Parameters
Ein generischer Typparameter kann von dem Typ stammen, den Sie untersuchen, von einem eingeschlossenen Typ oder von einer generischen Methode. Sie können die Quelle des generischen Typparameters wie folgt ermitteln:
- Verwenden Sie zunächst die DeclaringMethod Eigenschaft, um zu bestimmen, ob der Typparameter aus einer generischen Methode stammt. Wenn der Eigenschaftswert kein Nullverweis ist, handelt es sich bei der Quelle um eine generische Methode.
- Wenn die Quelle keine generische Methode ist, verwenden Sie die DeclaringType Eigenschaft, um den generischen Typ zu bestimmen, zu dem der generische Typparameter gehört.
Wenn der Typparameter zu einer generischen Methode gehört, gibt die DeclaringType Eigenschaft den Typ zurück, der die generische Methode deklariert hat, was irrelevant ist.
Position eines generischen Parameters
In seltenen Fällen ist es erforderlich, die Position eines Typparameters in der Typparameterliste der deklarierenden Klasse zu bestimmen. Angenommen, Sie haben ein Type Objekt, das den B<int, V>
Typ aus dem vorherigen Beispiel darstellt. Mit der GetGenericArguments-Methode erhalten Sie eine Liste von Typargumenten, und wenn Sie V
untersuchen, können Sie anhand der Eigenschaften DeclaringMethod und DeclaringType ermitteln, woher sie stammt. Anschließend können Sie die GenericParameterPosition Eigenschaft verwenden, um die Position in der Typparameterliste zu bestimmen, in der sie definiert wurde. In diesem Beispiel V
befindet sich die Position 0 (Null) in der Typparameterliste, in der sie definiert wurde.
Basistyp- und Schnittstelleneinschränkungen
Verwenden Sie die GetGenericParameterConstraints Methode, um die Basistypeinschränkung und Schnittstelleneinschränkungen eines Typparameters abzurufen. Die Reihenfolge der Elemente des Arrays ist nicht signifikant. Ein Element stellt eine Schnittstelleneinschränkung dar, wenn es sich um einen Schnittstellentyp handelt.
Generische Parameterattribute
Die GenericParameterAttributes Eigenschaft ruft einen GenericParameterAttributes Wert ab, der die Varianz (Kovarianz oder Kontravarianz) und die speziellen Einschränkungen eines Typparameters angibt.
Kovarianz und Kontravarianz
Um zu bestimmen, ob ein Typparameter kovariant oder kontravariant ist, wenden Sie die GenericParameterAttributes.VarianceMask Maske auf den Wert an, der von der Eigenschaft GenericParameterAttributes zurückgegeben wird. Wenn das Ergebnis lautet, ist GenericParameterAttributes.Noneder Typparameter invariant. Weitere Informationen finden Sie unter "Kovarianz" und "Contravariance".
Besondere Einschränkungen
Um die besonderen Einschränkungen eines Typparameters zu ermitteln, wenden Sie die GenericParameterAttributes.SpecialConstraintMask Maske auf den Wert an, der von der GenericParameterAttributes Eigenschaft zurückgegeben wird. Wenn das Ergebnis lautet GenericParameterAttributes.None, gibt es keine besonderen Einschränkungen. Ein Typparameter kann auf einen Verweistyp beschränkt werden, um ein nicht nullabler Werttyp zu sein und einen parameterlosen Konstruktor zu besitzen.
Invarianten
Eine Tabelle der invarianten Bedingungen für allgemeine Begriffe in Reflexion für generische Typen finden Sie unter Type.IsGenericType. Weitere Begriffe zu generischen Methoden finden Sie unter MethodBase.IsGenericMethod.