Generische Typen in Visual Basic (Visual Basic)

Ein generischer Typ ist ein einzelnes Programmierelement, das sich so anpasst, dass es für verschiedene Datentypen dieselben Funktionen ausführt. Wenn Sie eine generische Klasse oder Prozedur definieren, müssen Sie keine separate Version für jeden Datentyp definieren, für den Sie ggf. diese Funktionen ausführen möchten.

Eine Analogie hierzu ist ein Schraubendrehersatz mit auswechselbaren Einsätzen. Sie sehen sich die Schraube an und wählen das entsprechende Teil für diese Schraube aus (z. B. für eine Schlitzschraube, Kreuzschlitzschraube oder eine sternförmige Schraube). Sobald Sie den entsprechenden Einsatz in den Schraubendreher gesteckt haben, führen Sie mit dem Schraubendreher genau diese Funktion aus, d. h. Sie drehen die Schraube.

Schraubendrehersatz als generisches Werkzeug

Diagramm eines Schraubdrehersatzes als generischem Werkzeug

Wenn Sie einen generischen Typ definieren, parametrisieren Sie ihn mit einem oder mehreren Datentypen. Dadurch können die Datentypen mithilfe von Code an die Anforderungen angepasst werden. In Code können mehrere unterschiedliche Programmierelemente anhand des generischen Elements deklariert werden, von denen jedes für eine andere Gruppe von Datentypen ausgeführt wird. Die deklarierten Elemente führen jedoch alle dieselbe Logik aus, unabhängig von den verwendeten Datentypen.

Sie können beispielsweise eine Warteschlangeklasse erstellen und verwenden, die für einen bestimmten Datentyp, z. B. String, ausgeführt wird. Sie können eine solche Klasse anhand von System.Collections.Generic.Queue<T> deklarieren, wie im folgenden Beispiel veranschaulicht.

Public stringQ As New System.Collections.Generic.Queue(Of String)

Jetzt können Sie stringQ verwenden, um ausschließlich mit String-Werten zu arbeiten. Da stringQ speziell für String-Werte und nicht allgemein für Object-Werte verwendet wird, müssen Sie keine späte Bindung oder Typkonvertierung ausführen. Dies erspart Ausführungszeit und trägt zur Verringerung von Laufzeitfehlern bei.

Weitere Informationen über die Verwendung eines generischen Typs finden Sie unter Gewusst wie: Verwenden einer generischen Klasse (Visual Basic).

Beispiel für eine generische Klasse

Im folgenden Beispiel wird eine Skelettdefinition einer generischen Klasse veranschaulicht.

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 obigen 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 für t verschiedene Datentypen angeben. Im folgenden Beispiel werden zwei solcher Deklarationen veranschaulicht.

Public integerClass As New classHolder(Of Integer)
Friend stringClass As New classHolder(Of String)

Die vorangehenden Anweisungen deklarieren konstruierte Klassen, in denen ein bestimmter Typ den Typparameter ersetzt. Diese Ersetzung wird im gesamten Code in der konstruierten Klasse weitergegeben. Im folgenden Beispiel wird die processNewItem-Prozedur in integerClass dargestellt.

Public Sub processNewItem(ByVal newItem As Integer)
    Dim tempItem As Integer
    ' Inserted code now processes an Integer item.
End Sub

Ein ausführlicheres Beispiel finden Sie unter Gewusst wie: Definieren einer Klasse, die für unterschiedliche Datentypen die gleiche Funktionalität bereitstellen kann (Visual Basic).

Geeignete Programmierelemente

Sie können generische Klassen, Strukturen, Schnittstellen, Prozeduren und Delegaten definieren und verwenden. Beachten Sie, dass .NET Framework mehrere generische Klassen, Strukturen und Schnittstellen definiert, die häufig verwendete generische Elemente darstellen. Der System.Collections.Generic-Namespace stellt Wörterbücher, Listen, Warteschlangen und Stapel bereit. Bevor Sie ein eigenes generisches Element definieren, überprüfen Sie, ob es bereits in System.Collections.Generic verfügbar ist.

Prozeduren sind keine Typen. Sie können jedoch generische Prozeduren definieren und verwenden. Siehe Generische Prozeduren in Visual Basic.

Vorteile von generischen Typen

Ein generischer Typ fungiert als Grundlage zum Deklarieren mehrerer unterschiedlicher Programmierelemente, von denen jedes für einen bestimmten Datentyp ausgeführt wird. Zu einem generischen Typ gibt es folgende Alternativen:

  1. Ein einzelner Typ, der auf den Object-Datentyp angewendet wird.

  2. Ein Satz von typspezifischen Versionen des Typs, wobei jede Version über individuellen Code verfügt und auf einen speziellen Datentyp, z. B. String, Integer oder einen benutzerdefinierten Typ wie customer, angewendet wird.

Ein generischer Typ bietet gegenüber diesen Alternativen folgende Vorteile:

  • Typsicherheit. Generische Typen erzwingen die Typüberprüfung zur Kompilierzeit. Auf Object beruhende Typen akzeptieren jeden Datentyp, und Sie müssen Code schreiben, der überprüft, ob ein Eingabedatentyp zulässig ist. Mit generischen Typen kann der Compiler Typenkonflikte vor der Laufzeit abfangen.

  • Leistung. Generische Typen müssen kein Boxing und Unboxing auf Daten anwenden, da jeder speziell auf einen einzigen Datentyp angewendet wird. Auf Object basierende Operationen müssen auf Eingabedatentypen Boxing anwenden, um sie in Object zu konvertieren, und auf Daten Unboxing anwenden, die für die Ausgabe vorgesehen sind. Durch Boxing und Unboxing wird die Leistung verringert.

    Auf Object basierende Typen sind außerdem spät gebunden, d. h., dass der Zugriff auf ihre Member zusätzlichen Code zur Laufzeit erfordert. Hierdurch wird die Leistung ebenfalls verringert.

  • Codekonsolidierung. Der Code für einen generischen Typ muss nur einmal definiert werden. Ein Satz typspezifischer Versionen eines Typs muss in jeder Version denselben Code replizieren, wobei sich die Versionen nur im Datentyp für die jeweilige Version unterscheiden. Bei generischen Typen werden alle typspezifischen Versionen anhand des ursprünglichen generischen Typs generiert.

  • Wiederverwendung von Code. Code, der nicht von einem bestimmten Datentyp abhängt, kann für verschiedene Datentypen wiederverwendet werden, wenn der Datentyp generisch ist. Sie können ihn häufig sogar für einen Datentypen wiederverwenden, den Sie nicht nicht im Voraus bestimmen können.

  • IDE-Unterstützung. Wenn Sie einen anhand eines generischen Typs deklarierten konstruierten Typ verwenden, können Sie durch die IDE (Integrated Development Environment) weitere Unterstützung beim Verfassen des Codes erhalten. Beispielsweise kann IntelliSense™ die typspezifischen Optionen für ein Argument eines Konstruktors oder einer Methode anzeigen.

  • Generische Algorithmen. Generische Typen sind gut für abstrakte Algorithmen geeignet, die typunabhängig sind. Beispielsweise kann eine generische Prozedur, die Elemente mithilfe der IComparable-Schnittstelle sortiert, für jeden Datentyp verwendet werden, der IComparable implementiert.

Einschränkungen

Obwohl Code in der Definition eines generischen Typs so typunabhängig wie möglich sein sollte, müssen Sie eventuell eine bestimmte Fähigkeit eines beliebigen, für den generischen Datentyp bereitgestellten Datentyps als erforderlich festlegen. Wenn Sie z. B. zwei Elemente vergleichen möchten, um sie zu sortieren, muss ihr 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 Skelettdefinition einer Klasse mit einer Einschränkung veranschaulicht, die erfordert, dass das Typargument IComparable implementiert.

Public Class itemManager(Of t As IComparable)
    ' Insert code that defines class members.
End Class

Wenn darauf folgender Code eine Klasse aus itemManager zu erstellen versucht und hierzu einen Typ bereitstellt, der IComparable nicht implementiert, signalisiert der Compiler einen Fehler.

Typen von Einschränkungen

In einer Einschränkung können die folgenden Anforderungen in beliebiger Kombination angegeben werden:

  • Das Typargument muss mindestens eine Schnittstelle implementieren.

  • Das Typargument muss mit dem Typ höchstens einer Klasse übereinstimmen oder den Typ von höchstens einer Klasse erben.

  • Das Typargument muss einen parameterlosen Konstruktor für den Code verfügbar machen, der Objekte anhand des Typarguments erstellt.

  • Das Typargument muss ein Verweistyp oder ein Werttyp sein.

Wenn Sie mehrere Einschränkungen definieren müssen, verwenden Sie eine durch Trennzeichen getrennte Einschränkungsliste in geschweiften Klammern ({ }). Um festzulegen, dass ein zugreifbarer Konstruktor erforderlich ist, fügen Sie das Operator New (Visual Basic)-Schlüsselwort in die Liste ein. Um festzulegen, dass ein Verweistyp erforderlich ist, fügen Sie das Class-Schlüsselwort ein. Um festzulegen, dass ein Werttyp erforderlich ist, fügen Sie das Structure-Schlüsselwort ein.

Weitere Informationen über Einschränkungen finden Sie unter Typenliste (Visual Basic).

Beispiel für mehrere Einschränkungen

Im folgenden Beispiel wird die Skelettdefinition einer generischen Klasse mit einer Einschränkungsliste für den Typparameter veranschaulicht. In Code, der eine Instanz dieser Klasse erstellt, muss das Typargument sowohl die IComparable-Schnittstelle als auch die IDisposable-Schnittstelle implementieren, ein Verweistyp sein und einen zugreifbaren 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

In Bezug auf generische Typen werden die folgenden Begriffe verwendet:

  • Generischer Typ. Eine Definition einer Klasse, einer Struktur, einer Schnittstelle, einer Prozedur oder eines Delegaten, für deren bzw. dessen Deklaration Sie mindestens einen Datentyp angeben.

  • Typparameter. In der Definition eines generischen Typs ein Platzhalter für einen Datentyp, den Sie beim Deklarieren des Typs angeben.

  • Typargument. Ein spezieller Datentyp, der einen Typparameter ersetzt, wenn Sie einen konstruierten Typ anhand eines generischen Typs deklarieren.

  • Einschränkung Eine Bedingung für einen Typparameter, die das Typargument einschränkt, das Sie für den Typparameter angeben können. Eine Einschränkung kann festlegen, dass das Typargument eine bestimmte Schnittstelle implementieren muss, einer bestimmten Klasse angehören oder von einer bestimmten Klasse erben muss, über einen zugreifbaren parameterlosen Konstruktor verfügen muss, ein Verweistyp oder ein Werttyp sein muss. Sie können diese Einschränkungen kombinieren, doch Sie können höchstens eine Klasse angeben.

  • Konstruierter Typ. Eine Klasse, eine Struktur, eine Schnittstelle, eine Prozedur oder ein Delegat, die bzw. der anhand eines generischen Typs deklariert werden, indem Typargumente für dessen Typparameter angegeben werden.

Siehe auch

Aufgaben

Problembehandlung bei Datentypen (Visual Basic)

Referenz

Datentyp: Zusammenfassung (Visual Basic)

Of-Klausel (Visual Basic)

As

Object-Datentyp

Konzepte

Datentypen in Visual Basic

Typzeichen (Visual Basic)

Weitere Ressourcen

Datentypimplementierung (Visual Basic)

Typkonvertierung in Visual Basic

Kovarianz und Kontravarianz (C# und Visual Basic)