Generische Typen in Visual Basic (Visual Basic)
Ein generischer Typ ist ein einzelnes Programmierelement, das sich an dieselbe Funktionalität für mehrere Datentypen anpasst. Wenn Sie eine generische Klasse oder Prozedur definieren, müssen Sie keine separate Version für jeden Datentyp definieren, für den Sie diese Funktionalität ausführen möchten.
Eine Analogie ist ein Schraubenziehersatz mit wechselbaren Köpfen. Sie sehen sich die Schraube an und wählen die geeignete Spitze für diese Schraube aus (geschlitzt, gekreuzt oder mit Stern). Sobald Sie den richtigen Kopf in den Schraubenziehergriff einlegen, führen Sie die gleiche Funktion mit dem Schraubenzieher aus, nämlich um die Schraube zu drehen.
Wenn Sie einen generischen Typ definieren, parametrisieren Sie ihn mit einem oder mehreren Datentypen. Typparameter ermöglichen es dem Code, die Datentypen auf seine Anforderungen anzupassen. Ihr Code kann mehrere verschiedene Programmierelemente aus dem generischen Element deklarieren, die jeweils auf eine andere Gruppe von Datentypen wirken. Aber die deklarierten Elemente führen alle die identische Logik aus, unabhängig davon, welche Datentypen sie verwenden.
Sie können z. B. eine Warteschlangenklasse erstellen und verwenden, die für einen bestimmten Datentyp wie String
arbeitet. Sie können eine solche Klasse aus System.Collections.Generic.Queue<T>deklarieren, wie im folgenden Beispiel gezeigt.
Public stringQ As New System.Collections.Generic.Queue(Of String)
Sie können jetzt stringQ
verwenden, um ausschließlich mit String
Werten zu arbeiten. Da stringQ
für String
spezifisch ist, anstatt für Object
Werte generalisiert zu werden, haben Sie keine späte Bindung oder Typkonvertierung. Generische Typen sparen Ausführungszeit und reduzieren Laufzeitfehler.
Weitere Informationen zur Verwendung eines generischen Typs finden Sie unter How to: Use a Generic Class.
Beispiel für eine generische Klasse
Das folgende Beispiel zeigt eine Skelettdefinition einer generischen Klasse.
Public Class classHolder(Of t)
Public Sub processNewItem(ByVal newItem As t)
Dim tempItem As t
' Insert code that processes an item of data type t.
End Sub
End Class
Im vorherigen Skelett ist t
ein Typparameter, d. h. ein Platzhalter für einen Datentyp, den Sie beim Deklarieren der Klasse angeben. An anderer Stelle im Code können Sie verschiedene Versionen von classHolder
deklarieren, indem Sie verschiedene Datentypen für t
bereitstellen. Das folgende Beispiel zeigt zwei solche Deklarationen.
Public integerClass As New classHolder(Of Integer)
Friend stringClass As New classHolder(Of String)
Die obigen Anweisungen deklarieren konstruierte Klassen, in denen ein bestimmter Typ den Typparameter ersetzt. Dieser Ersatz wird im gesamten Code innerhalb der konstruierten Klasse weitergegeben. Das folgende Beispiel zeigt, wie die processNewItem
Prozedur in integerClass
aussieht.
Public Sub processNewItem(ByVal newItem As Integer)
Dim tempItem As Integer
' Inserted code now processes an Integer item.
End Sub
Ein vollständigeres Beispiel finden Sie unter So definieren Sie eine Klasse, die identische Funktionalität für verschiedene Datentypen bereitstellen kann.
Berechtigte Programmierungselemente
Sie können generische Klassen, Strukturen, Schnittstellen, Prozeduren und Delegaten definieren und verwenden. .NET definiert mehrere generische Klassen, Strukturen und Schnittstellen, die häufig verwendete generische Elemente darstellen. Der System.Collections.Generic-Namespace stellt Wörterbücher, Listen, Warteschlangen und Stapel bereit. Bevor Sie Ihr eigenes generisches Element definieren, überprüfen Sie, ob es bereits in System.Collections.Genericverfügbar ist.
Prozeduren sind keine Typen, Aber Sie können generische Prozeduren definieren und verwenden. Siehe generische Prozeduren in Visual Basic.
Vorteile generischer Typen
Ein generischer Typ dient als Grundlage für die Deklarierung mehrerer verschiedener Programmierelemente, die jeweils für einen bestimmten Datentyp verwendet werden. Die Alternativen zu einem generischen Typ sind:
- Ein einziger Typ, der auf dem
Object
-Datentyp arbeitet. - Eine Reihe von typspezifischen Versionen des Typs. Jede Version wird einzeln codiert und auf einem bestimmten Datentyp wie
String
,Integer
oder einem benutzerdefinierten Typ wiecustomer
ausgeführt.
Ein generischer Typ hat gegenüber diesen Alternativen die folgenden Vorteile:
- Typsicherheit . Generische Typen erzwingen die Typüberprüfung zur Kompilierzeit. Typen, die auf
Object
basieren, akzeptieren jeden Datentyp, und Sie müssen Code schreiben, um zu überprüfen, ob ein Eingabedatentyp akzeptabel ist. Bei generischen Typen kann der Compiler Typenkonflikten vor der Laufzeit abfangen. - Leistung. Generische Typen müssen kein Boxing und Unboxing für Daten ausführen, da jeder Typ speziell für einen Datentyp verwendet wird. Operationen, die auf
Object
basierend, müssen für Eingabedatentypen Boxing ausführen, um sie inObject
zu konvertieren, und Unboxing für Daten ausführen, die für die Ausgabe vorgesehen sind. Boxen und Entboxen reduzieren die Leistung. Typen, die aufObject
basieren, sind außerdem spät gebunden, d. h., dass der Zugriff auf ihre Member zusätzlichen Code zur Laufzeit erfordert. Typkonvertierungen verringern auch die Leistung. - Codekonsolidierung. Der Code in einem generischen Typ muss nur einmal definiert werden. Eine Gruppe typspezifischer Versionen eines Typs muss denselben Code in jeder Version replizieren, wobei der einzige Unterschied der spezifische Datentyp für diese Version ist. Bei generischen Typen werden alle typspezifischen Versionen aus dem ursprünglichen generischen Typ generiert.
- Codewiederverwendung Code, der nicht von einem bestimmten Datentyp abhängt, kann mit verschiedenen Datentypen wiederverwendet werden, wenn er generisch ist. Sie können sie häufig auch mit einem Datentyp wiederverwenden, den Sie ursprünglich nicht vorhergesagt haben.
- IDE-Unterstützung. Wenn Sie einen konstruierten Typ verwenden, der aus einem generischen Typ deklariert ist, kann ihnen die integrierte Entwicklungsumgebung (Integrated Development Environment, IDE) mehr Unterstützung bieten, während Sie Ihren Code entwickeln. IntelliSense kann z. B. die typspezifischen Optionen für ein Argument für einen Konstruktor oder eine Methode anzeigen.
- Generische Algorithmen. Abstrakte Algorithmen, die typunabhängig sind, sind gute Kandidaten für generische Typen. Beispielsweise kann eine generische Prozedur, die Elemente mithilfe der IComparable Schnittstelle sortiert, mit jedem Datentyp verwendet werden, der IComparableimplementiert.
Zwänge
Obwohl der Code in einer generischen Typdefinition so typunabhängig wie möglich sein sollte, müssen Sie möglicherweise eine bestimmte Funktion eines beliebigen Datentyps erfordern, der für den generischen Typ bereitgestellt wird. Wenn Sie beispielsweise zwei Elemente zum Sortieren oder Zusammenstellen vergleichen möchten, muss deren Datentyp die IComparable-Schnittstelle implementieren. Sie können diese Anforderung erzwingen, indem Sie dem Typparameter eine Einschränkung hinzufügen.
Beispiel für eine Einschränkung
Im folgenden Beispiel wird die Rumpfdefinition einer Klasse mit einer Einschränkung gezeigt, die für das Typargument erfordert, dass es IComparableimplementiert.
Public Class itemManager(Of t As IComparable)
' Insert code that defines class members.
End Class
Wenn der nachfolgende Code versucht, aus itemManager
eine Klasse mit einem Typ zu erstellen, der IComparablenicht implementiert, meldet der Compiler einen Fehler.
Arten von Einschränkungen
Ihre Einschränkung kann die folgenden Anforderungen in einer beliebigen Kombination angeben:
- Das Typargument muss eine oder mehrere Schnittstellen implementieren.
- Das Typargument darf nur den Typ einer einzigen Klasse haben oder von einer einzigen Klasse erben.
- Das Typargument muss einen parameterlosen Konstruktor verfügbar machen, auf den der Code zugreifen kann, der Objekte daraus erstellt.
- Das Typargument muss ein Verweistypsein oder ein Werttyp sein.
C#-Code kann deklarieren, dass ein Typargument ein nicht verwalteter Typsein muss. Visual Basic erzwingt diese Einschränkung für Visual Basic-Code, der einen generischen Typ oder eine methode verwendet, der mit dieser Einschränkung (in C#) definiert wurde. Sie können jedoch keine unmanaged
Einschränkung für einen Typparameter in Visual Basic deklarieren.
Wenn Sie mehrere Anforderungen auferlegen müssen, verwenden Sie eine durch Trennzeichen getrennte Einschränkungsliste in geschweiften Klammern ({ }
). Um einen barrierefreien Konstruktor zu benötigen, fügen Sie das schlüsselwort New Operator in die Liste ein. Um einen Verweistyp zu benötigen, fügen Sie das schlüsselwort Class
ein; um einen Werttyp zu erfordern, fügen Sie das schlüsselwort Structure
ein.
Weitere Informationen zu Einschränkungen finden Sie unter Typliste.
Beispiel für mehrere Einschränkungen
Das folgende Beispiel zeigt eine Skelettdefinition einer generischen Klasse mit einer Einschränkungsliste für den Typparameter. Im Code, der eine Instanz dieser Klasse erstellt, muss das Typargument sowohl die IComparable als auch IDisposable Schnittstellen implementieren, ein Verweistyp sein und einen barrierefreien parameterlosen Konstruktor verfügbar machen.
Public Class thisClass(Of t As {IComparable, IDisposable, Class, New})
' Insert code that defines class members.
End Class
Wichtige Begriffe
Generische Typen führen die folgenden Begriffe ein und verwenden sie:
- Generischer Typ. Eine Definition einer Klasse, Struktur, Schnittstelle, Prozedur oder Stellvertretung, für die Sie beim Deklarieren mindestens einen Datentyp angeben.
- Typ-Parameter. In der Definition eines generischen Typs ein Platzhalter für einen Datentyp, den Sie beim Deklarieren des Typs angeben.
- Typargument. Ein bestimmter Datentyp, der einen Typparameter ersetzt, wenn Sie einen konstruierten Typ aus einem generischen Typ deklarieren.
- Einschränkung. Eine Bedingung für einen Typparameter, der das Typargument einschränkt, das Sie angeben können. Eine Einschränkung kann erfordern, dass das Typargument eine bestimmte Schnittstelle implementiert, von einer bestimmten Klasse erbt, einen barrierefreien parameterlosen Konstruktor aufweist oder ein Verweistyp oder ein Werttyp sein kann. Sie können diese Einschränkungen kombinieren, aber Sie können höchstens eine Basisklasse angeben.
- Konstruierter Typ. Eine Klasse, Struktur, Schnittstelle, Prozedur oder Stellvertretung, die von einem generischen Typ deklariert wird, indem Typargumente für die Typparameter bereitgestellt werden.