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.
Mit Generika können Sie eine Methode, Klasse, Struktur oder Schnittstelle auf den genauen Datentyp anpassen, auf den sie wirkt. Beispielsweise können Sie anstelle der Klasse Hashtable, bei der Schlüssel und Werte beliebiger Art sein können, die generische Klasse Dictionary<TKey,TValue> verwenden und die zulässigen Typen für Schlüssel und Wert angeben. Unter den Vorteilen von Generika sind erhöhte Code-Wiederverwendbarkeit und Typsicherheit.
Definieren und Verwenden von Generika
Generika sind Klassen, Strukturen, Schnittstellen und Methoden, die Platzhalter (Typparameter) für einen oder mehrere der Typen aufweisen, die sie speichern oder verwenden. Eine generische Auflistungsklasse verwendet möglicherweise einen Typparameter als Platzhalter für den Objekttyp, den sie speichert. Die Typparameter werden als Typen ihrer Felder und die Parametertypen ihrer Methoden angezeigt. Eine generische Methode kann den Typparameter als Typ des Rückgabewerts oder als Typ eines der formalen Parameter verwenden.
Der folgende Code veranschaulicht eine einfache generische Klassendefinition.
public class SimpleGenericClass<T>
{
public T Field;
}
Public Class SimpleGenericClass(Of T)
Public Field As T
End Class
Wenn Sie eine Instanz einer generischen Klasse erstellen, geben Sie die tatsächlichen Typen an, die durch die Typparameter ersetzt werden sollen. Dadurch wird eine neue generische Klasse eingerichtet, die als konstruierte generische Klasse bezeichnet wird, wobei die ausgewählten Typen überall ersetzt werden, wo die Typparameter angezeigt werden. Das Ergebnis ist eine typsichere Klasse, die auf Ihre Auswahl von Typen zugeschnitten ist, wie der folgende Code veranschaulicht.
public static void Main()
{
SimpleGenericClass<string> g = new SimpleGenericClass<string>();
g.Field = "A string";
//...
Console.WriteLine($"SimpleGenericClass.Field = \"{g.Field}\"");
Console.WriteLine($"SimpleGenericClass.Field.GetType() = {g.Field.GetType().FullName}");
}
Public Shared Sub Main()
Dim g As New SimpleGenericClass(Of String)
g.Field = "A string"
'...
Console.WriteLine("SimpleGenericClass.Field = ""{0}""", g.Field)
Console.WriteLine("SimpleGenericClass.Field.GetType() = {0}", g.Field.GetType().FullName)
End Sub
Terminologie
Die folgenden Begriffe werden verwendet, um Generisches in .NET zu besprechen:
Eine generische Typdefinition ist eine Klassen-, Struktur- oder Schnittstellendeklaration, die als Vorlage funktioniert, mit Platzhaltern für die Typen, die sie enthalten oder verwenden kann. Zum Beispiel kann die System.Collections.Generic.Dictionary<TKey,TValue>-Klasse zwei Typen enthalten: Schlüssel und Werte. Da es sich bei einer generischen Typdefinition nur um eine Vorlage handelt, können Sie keine Instanzen einer Klasse, Struktur oder Schnittstelle erstellen, die eine generische Typdefinition ist.
Generische Typparameter oder Typparameter sind die Platzhalter in einer generischen Typ- oder Methodendefinition. Der System.Collections.Generic.Dictionary<TKey,TValue> generische Typ hat zwei Typparameter,
TKeyundTValue, die die Typen seiner Schlüssel und Werte darstellen.Ein konstruierter generischer Typ oder konstruierter Typ ist das Ergebnis der Angabe von Typen für die generischen Typparameter einer generischen Typdefinition.
Ein generisches Typargument ist ein beliebiger Typ, der durch einen generischen Typparameter ersetzt wird.
Der allgemeine Begriff "Generischer Typ " enthält sowohl konstruierte Typen als auch generische Typdefinitionen.
Kovarianz und Kontravarianz generischer Typparameter ermöglichen es Ihnen, konstruierte generische Typen zu verwenden, deren Typargumente abgeleiteter (Kovarianz) oder weniger abgeleitet (Kontravarianz) als ein konstruierter Zieltyp sind. Kovarianz und Kontravarianz werden gemeinsam als Varianz bezeichnet. Weitere Informationen finden Sie unter "Kovarianz" und "Kontravarianz".
Einschränkungen gelten für generische Typparameter. Sie können beispielsweise einen Typparameter auf Typen beschränken, die die System.Collections.Generic.IComparer<T> generische Schnittstelle implementieren, um sicherzustellen, dass Instanzen des Typs sortiert werden können. Sie können auch Typparameter auf Typen beschränken, die eine bestimmte Basisklasse aufweisen, die einen parameterlosen Konstruktor aufweisen oder Bezugstypen oder Werttypen sind. Benutzer des generischen Typs können keine Typenargumente ersetzen, die die Einschränkungen nicht erfüllen.
Eine generische Methodendefinition ist eine Methode mit zwei Parameterlisten: eine Liste generischer Typparameter und eine Liste formaler Parameter. Typparameter können als Rückgabetyp oder als Typen der formalen Parameter angezeigt werden, wie der folgende Code zeigt.
T MyGenericMethod<T>(T arg) { T temp = arg; //... return temp; }Function MyGenericMethod(Of T)(ByVal arg As T) As T Dim temp As T = arg '... Return temp End FunctionGenerische Methoden können für generische oder nichtgenerische Typen angezeigt werden. Es ist wichtig zu beachten, dass eine Methode nicht generisch ist, nur weil sie zu einem generischen Typ gehört, oder auch weil sie formale Parameter enthält, deren Typen die generischen Parameter des eingeschlossenen Typs sind. Eine Methode ist nur generisch, wenn sie über eine eigene Liste von Typparametern verfügt. Im folgenden Code ist nur die Methode
Ggenerisch.class A { T G<T>(T arg) { T temp = arg; //... return temp; } } class MyGenericClass<T> { T M(T arg) { T temp = arg; //... return temp; } }Class A Function G(Of T)(ByVal arg As T) As T Dim temp As T = arg '... Return temp End Function End Class Class MyGenericClass(Of T) Function M(ByVal arg As T) As T Dim temp As T = arg '... Return temp End Function End Class
Vor- und Nachteile von Generika
Es gibt viele Vorteile bei der Verwendung generischer Sammlungen und Stellvertretungen:
Typsicherheit. Generics verschiebt die Belastung der Typsicherheit von Ihnen in den Compiler. Es ist nicht erforderlich, Code zu schreiben, um den richtigen Datentyp zu testen, da er zur Kompilierungszeit erzwungen wird. Die Notwendigkeit von Typumwandlungen und die Möglichkeit von Laufzeitfehlern werden verringert.
Weniger Code und einfachere Wiederverwendbarkeit. Es ist nicht erforderlich, von einem Basistyp zu erben und Member außer Kraft zu setzen. Zum Beispiel ist LinkedList<T> sofort einsatzbereit. Sie können beispielsweise eine verknüpfte Liste mit Zeichenfolgen mit der folgenden Variablendeklaration erstellen:
LinkedList<string> llist = new LinkedList<string>();Dim llist As New LinkedList(Of String)()Bessere Leistung. Generische Sammlungstypen können im Allgemeinen besser zum Speichern und Bearbeiten von Werttypen verwendet werden, da es nicht erforderlich ist, die Werttypen zu boxen.
Generische Delegaten ermöglichen typsichere Callbacks, ohne dass mehrere Delegatenklassen erstellt werden müssen. Mit dem Predicate<T> generischen Delegat können Sie z. B. eine Methode erstellen, die Ihre eigenen Suchkriterien für einen bestimmten Typ implementiert und Ihre Methode mit Methoden des Array Typs wie Find, FindLast und FindAll verwenden.
Generics rationalisieren dynamisch generierten Code. Wenn Sie Generika mit dynamisch generierten Code verwenden, müssen Sie den Typ nicht generieren. Dadurch wird die Anzahl der Szenarien erhöht, in denen Sie einfache dynamische Methoden verwenden können, anstatt ganze Assemblys zu generieren. Weitere Informationen finden Sie unter How to: Define and Execute Dynamic Methods and DynamicMethod.
Im Folgenden sind einige Einschränkungen von Generika aufgeführt:
Generische Typen können von den meisten Basisklassen abgeleitet werden, wie z. B. MarshalByRefObject (und durch Einschränkungen kann verlangt werden, dass generische Typparameter von Basisklassen abgeleitet werden, wie z. B. MarshalByRefObject). .NET unterstützt jedoch keine kontextgebundenen generischen Typen. Ein generischer Typ kann von ContextBoundObject abgeleitet werden, aber der Versuch, eine Instanz davon zu erstellen, führt zu einer TypeLoadException.
Enumerationen können keine generischen Typparameter aufweisen. Eine Aufzählung kann nur zufällig generisch sein (z. B. weil sie in einem generischen Typ geschachtelt ist, der mit Visual Basic, C# oder C++ definiert ist). Weitere Informationen finden Sie unter "Enumerationen" im allgemeinen Typsystem.
Einfache dynamische Methoden können nicht generisch sein.
In Visual Basic, C# und C++ kann ein geschachtelter Typ, der in einen generischen Typ eingeschlossen ist, nicht instanziiert werden, es sei denn, Typen wurden den Typparametern aller eingeschlossenen Typen zugewiesen. Anders ausgedrückt, enthält ein geschachtelter Typ, der in diesen Sprachen definiert ist, die Typparameter aller ihn umfassenden Typen. Dadurch können die Typparameter von eingeschlossenen Typen in den Memberdefinitionen eines geschachtelten Typs verwendet werden. Weitere Informationen finden Sie unter "Geschachtelte Typen" in MakeGenericType.
Hinweis
Ein geschachtelter Typ, der durch Das Senden von Code in einer dynamischen Assembly oder mithilfe des Ilasm.exe (IL Assembler) definiert wird, ist nicht erforderlich, um die Typparameter seiner eingeschlossenen Typen einzuschließen; Wenn sie jedoch nicht enthalten sind, befinden sich die Typparameter nicht im Bereich der geschachtelten Klasse.
Weitere Informationen finden Sie unter "Geschachtelte Typen" in MakeGenericType.
Klassenbibliothek und Sprachunterstützung
.NET stellt eine Reihe generischer Auflistungsklassen in den folgenden Namespaces bereit:
Der System.Collections.Generic-Namespace enthält die meisten generischen Auflistungstypen, die von .NET bereitgestellt werden, z. B. die generischen Klassen List<T> und Dictionary<TKey,TValue>.
Der System.Collections.ObjectModel Namespace enthält zusätzliche generische Auflistungstypen, z. B. die ReadOnlyCollection<T> generische Klasse, die für das Verfügbarmachen von Objektmodellen für Benutzer Ihrer Klassen nützlich sind.
Generische Schnittstellen für die Implementierung von Sortier- und Gleichheitsvergleichen werden im System Namespace sowie generische Delegattypen für Ereignishandler, Konvertierungen und Such-Prädikate bereitgestellt.
Der System.Numerics Namespace stellt generische Schnittstellen für mathematische Funktionen bereit (verfügbar in .NET 7 und höher). Weitere Informationen finden Sie unter Generische Mathematik.
Unterstützung für Generika wurde dem System.Reflection Namespace zum Untersuchen generischer Typen und generischer Methoden hinzugefügt, zum Erstellen von dynamischen Assemblys, die generische Typen und Methoden enthalten, und zum System.Reflection.Emit Generieren von Quelldiagrammen, die Generika enthalten.
Die Common Language Runtime bietet neue Opcodes und Präfixe zur Unterstützung generischer Typen in allgemeiner Zwischensprache (CIL), einschließlich Stelem, , Ldelem, Unbox_Any, Constrainedund Readonly.
Visual C++, C# und Visual Basic bieten umfassende Unterstützung für die Definition und Verwendung von Generika. Weitere Informationen zur Sprachunterstützung finden Sie unter Generic Types in Visual Basic, Introduction to Generics und Overview of Generics in Visual C++.
Geschachtelte Typen und Generika
Ein Typ, der in einem generischen Typ geschachtelt ist, kann von den Typparametern des eingeschlossenen generischen Typs abhängen. Die Common Language Runtime betrachtet geschachtelte Typen als generisch, auch wenn sie keine generischen Typparameter besitzen. Wenn Sie eine Instanz eines geschachtelten Typs erstellen, müssen Sie Typargumente für alle eingeschlossenen generischen Typen angeben.
Verwandte Artikel
| Titel | BESCHREIBUNG |
|---|---|
| Generische Auflistungen in .NET | Beschreibt generische Auflistungsklassen und andere generische Typen in .NET. |
| Generische Delegaten zum Bearbeiten von Arrays und Listen | Beschreibt generische Delegaten für Konvertierungen, Such-Prädikate und Aktionen, die für Elemente eines Arrays oder einer Auflistung ausgeführt werden sollen. |
| Generische Mathematik | Beschreibt, wie Sie mathematische Vorgänge generisch ausführen können. |
| Generische Schnittstellen | Beschreibt generische Schnittstellen, die allgemeine Funktionen für familienübergreifende generische Typen bereitstellen. |
| Kovarianz und Kontravarianz | Beschreibt die Kovarianz und Kontravarianz in generischen Typparametern. |
| Häufig verwendete Sammlungstypen | Enthält zusammenfassende Informationen zu den Merkmalen und Verwendungsszenarien der Sammlungstypen in .NET, einschließlich generischer Typen. |
| Gründe für die Verwendung generischer Sammlungen | Beschreibt allgemeine Regeln zum Bestimmen, wann generische Auflistungstypen verwendet werden sollen. |
| Vorgehensweise: Definieren eines generischen Typs mit Reflection Emit | Erläutert, wie dynamische Assemblys erstellt werden, die generische Typen und Methoden enthalten. |
| Generische Typen in Visual Basic | Beschreibt das Generics-Feature für Visual Basic-Benutzer, einschließlich Anleitungsthemen für die Verwendung und Definition generischer Typen. |
| Einführung in Generika | Bietet eine Übersicht über das Definieren und Verwenden generischer Typen für C#-Benutzer. |
| Übersicht über Generics in Visual C++ | Beschreibt das Generika-Feature für C++-Benutzer, einschließlich der Unterschiede zwischen Generika und Vorlagen. |