Anonyme Typen (Visual Basic)

Visual Basic untersützt anonyme Typen, mit denen Objekte erzeugt werden können, ohne eine Klassendefinition für den Datentyp zu schreiben. Stattdessen erzeugt der Compiler eine Klasse. Die Klasse hat keinen verwendbaren Namen, erbt direkt von Object und enthält die von Ihnen in der Deklaration des Objekts angegebenen Eigenschaften. Da der Name des Datentyps nicht angegeben wird, wird er als anonymer Typ bezeichnet.

Im folgenden Beispiel wird die Variable product als Instanz eines anonymen Typs mit den beiden Eigenschaften Name und Price deklariert und erzeugt.

' Variable product is an instance of a simple anonymous type.
Dim product = New With {Key .Name = "paperclips", .Price = 1.29}

Ein Abfrageausdruck verwendet anonyme Typen, um Spalten mit Daten, die durch eine Abfrage ausgewählt wurden, zusammenzustellen. Der Typ des Ergebnisses kann nicht im Voraus definiert werden, da die Spalten, die von einer bestimmten Abfrage ausgewählt werden, nicht vorausgesehen werden können. Anonyme Typen ermöglichen das Schreiben einer Abfrage, die eine beliebige Anzahl von Spalten in beliebiger Reihenfolge auswählt. Der Compiler erstellt einen Datentyp, der zu den angegebenen Eigenschaften und der angegebenen Reihenfolge passt.

In den folgenden Beispielen ist products eine Liste von Product-Objekten, von denen jedes eine Reihe von Eigenschaften hat. Die Variable namePriceQuery enthält die Definition einer Abfrage, die bei ihrer Ausführung eine Auflistung von Instanzen eines anonymen Typs zurückgibt, der die beiden Eigenschaften Name und Price hat.

Dim namePriceQuery = From prod In products
                     Select prod.Name, prod.Price

Die Variable nameQuantityQuery enthält die Definition einer Abfrage, die bei ihrer Ausführung eine Auflistung von Instanzen eines anonymen Typs zurückgibt, der die beiden Eigenschaften Name und OnHand hat.

Dim nameQuantityQuery = From prod In products
                        Select prod.Name, prod.OnHand

Weitere Informationen über den Code, der vom Compiler für einen anonymen Typ erstellt wird, finden Sie unter Definition von anonymen Typen (Visual Basic).

Warnung

Der Name des anonymen Typs wird vom Compiler erzeugt und kann von Kompilierung zu Kompilierung variieren. Sie sollten im Code den Namen eines anonymen Typs nicht verwenden oder sich darauf verlassen, da er sich bei einer Neukompilierung des Projekts ändern könnte.

Deklarieren eines anonymen Typs

Die Deklaration einer Instanz eines anonymen Typs verwendet eine Initialisiererliste zur Angabe der Eigenschaften des Typs. Bei der Deklaration eines anonymen Typs können nur Eigenschaften angegeben werden, keine anderen Klassenelemente wie Methoden oder Ereignisse. Im folgenden Beispiel ist product1 eine Instanz eines anonymen Typs mit zwei Eigenschaften: Name und Price.

' Variable product1 is an instance of a simple anonymous type.
Dim product1 = New With {.Name = "paperclips", .Price = 1.29}
' -or-
' product2 is an instance of an anonymous type with key properties.
Dim product2 = New With {Key .Name = "paperclips", Key .Price = 1.29}

Wenn Sie Eigenschaften als Haupteigenschaften festlegen, können Sie sie verwenden, um zwei Instanzen eines anonymen Typs auf Gleichheit zu testen. Die Werte von Haupteigenschaften können jedoch nicht geändert werden. Weitere Informationen finden Sie weiter unten in diesem Thema im Abschnitt "Haupteigenschaften".

Beachten Sie, dass die Deklaration einer Instanz eines anonymen Typs der Deklaration eines benannten Typs mithilfe eines Objektinitialisierers entspricht:

' Variable product3 is an instance of a class named Product.
Dim product3 = New Product With {.Name = "paperclips", .Price = 1.29}

Einen ausführlicheren Vergleich der Deklaration von benannten und anonymen Typen finden Sie unter Benannte Typen im Vergleich zu anonymen Typen (Visual Basic).

Weitere Informationen über andere Möglichkeiten, Eigenschaften von anonymen Typen anzugeben, finden Sie unter Gewusst wie: Ableiten von Eigenschaftennamen und Typen in Deklarationen von anonymen Typen (Visual Basic).

Haupteigenschaften

Haupteigenschaften unterscheiden sich von Eigenschaften, die keine Haupteigenschaften sind, in mehreren grundlegenden Punkten:

  • Nur die Werte von Haupteigenschaften werden verglichen, um zu ermitteln, ob zwei Instanzen gleich sind.

  • Die Werte von Haupteigenschaften sind schreibgeschützt und können nicht geändert werden.

  • Nur Werte von Haupteigenschaften sind in dem vom Compiler generierten Hashcodealgorithmus für den anonymen Typ enthalten.

Gleichheit

Instanzen anonymer Typen können nur gleich sein, wenn sie Instanzen des gleichen anonymen Typs sind. Der Compiler behandelt zwei Instanzen als Instanzen des gleichen Typs, wenn sie die folgenden Bedingungen erfüllen:

  • Sie werden in der gleichen Assembly deklariert.

  • Ihre Eigenschaften haben die gleichen Namen, die gleichen abgeleiteten Typen und werden in der gleichen Reihenfolge deklariert. Beim Vergleichen von Namen wird die Groß- und Kleinschreibung nicht berücksichtigt.

  • In beiden sind die gleichen Eigenschaften als Haupteigenschaften gekennzeichnet.

  • Mindestens eine Eigenschaft in jeder Deklaration ist eine Haupteigenschaft.

Eine Instanz eines anonymen Typs, der keine Haupteigenschaften hat, gleicht nur sich selbst.

' prod1 and prod2 have no key values.
Dim prod1 = New With {.Name = "paperclips", .Price = 1.29}
Dim prod2 = New With {.Name = "paperclips", .Price = 1.29}

' The following line displays False, because prod1 and prod2 have no
' key properties.
Console.WriteLine(prod1.Equals(prod2))

' The following statement displays True because prod1 is equal to itself.
Console.WriteLine(prod1.Equals(prod1))

Zwei Instanzen desselben anonymen Typs sind gleich, wenn die Werte ihrer Haupteigenschaften übereinstimmen. In den folgenden Beispielen wird veranschaulicht, wie auf Gleichheit getestet wird.

Dim prod3 = New With {Key .Name = "paperclips", Key .Price = 1.29}
Dim prod4 = New With {Key .Name = "paperclips", Key .Price = 1.29}
' The following line displays True, because prod3 and prod4 are
' instances of the same anonymous type, and the values of their
' key properties are equal.
Console.WriteLine(prod3.Equals(prod4))

Dim prod5 = New With {Key .Name = "paperclips", Key .Price = 1.29}
Dim prod6 = New With {Key .Name = "paperclips", Key .Price = 1.29,
                      .OnHand = 423}
' The following line displays False, because prod5 and prod6 do not 
' have the same properties.
Console.WriteLine(prod5.Equals(prod6))

Dim prod7 = New With {Key .Name = "paperclips", Key .Price = 1.29,
                      .OnHand = 24}
Dim prod8 = New With {Key .Name = "paperclips", Key .Price = 1.29,
                      .OnHand = 423}
' The following line displays True, because prod7 and prod8 are
' instances of the same anonymous type, and the values of their
' key properties are equal. The equality check does not compare the
' values of the non-key field.
Console.WriteLine(prod7.Equals(prod8))

Schreibgeschützte Werte

Die Werte von Haupteigenschaften können nicht geändert werden. In prod8 aus dem vorhergehenden Beispiel sind die Felder Name und Price read-only, OnHand kann jedoch geändert werden.

        ' The following statement will not compile, because Name is a key
        ' property and its value cannot be changed.
        ' prod8.Name = "clamps"

        ' OnHand is not a Key property. Its value can be changed.
        prod8.OnHand = 22

Anonyme Typen aus Abfrageausdrücken

Abfrageausdrücke erfordern nicht immer die Erstellung anonymer Typen. Wenn möglich wird ein vorhandener Typ für die Spaltendaten verwendet. Dies ist der Fall, wenn die Abfrage entweder ganze Datensätze aus der Datenquelle oder nur ein Feld jedes Datensatzes zurückgibt. In den folgenden Codebeispielen ist customers eine Auflistung von Objekten einer Customer-Klasse. Die Klasse hat eine Reihe von Eigenschaften, von denen eine oder mehrere in beliebiger Reihenfolge dem Abfrageergebnis hinzugefügt werden können. In den ersten beiden Beispielen werden keine anonymen Typen benötigt, da die Abfragen Elemente von benannten Typen auswählen:

  • custs1 enthält eine Auflistung von Zeichenfolgen, da cust.Name eine Zeichenfolge ist.

    Dim custs1 = From cust In customers
                 Select cust.Name
    
  • custs2 enthält eine Auflistung von Customer-Objekten, da jedes Element von customers ein Customer-Objekt ist und das ganze Element von der Abfrage ausgewählt wird.

    Dim custs2 = From cust In customers
                 Select cust
    

Passende benannte Typen sind jedoch nicht immer verfügbar. Möglicherweise möchten Sie Kundennamen und -adressen zu einem bestimmten Zweck, Kunden-ID-Nummern und Standorte zu einem anderen Zweck und Kundennamen, -adressen und Bestellhistorien zu einem dritten Zweck auswählen. Anonyme Typen ermöglichen die Auswahl beliebiger Kombinationen von Eigenschaften in beliebiger Reihenfolge, ohne dass die Deklaration eines benannten Typs für das Ergebnis notwendig ist. Stattdessen erstellt der Compiler einen anonymen Typ für jede Zusammenstellung von Eigenschaften. Die folgende Abfrage wählt nur den Namen des Kunden und die ID-Nummer von jedem Customer-Objekt in customers aus. Daher erstellt der Compiler einen anonymen Typ, der nur diese beiden Eigenschaften enthält.

Dim custs3 = From cust In customers
             Select cust.Name, cust.ID

Sowohl die Namen als auch die Datentypen der Eigenschaften des anonymen Typs werden von den Argumenten von Select übernommen: cust.Name und cust.ID. Die Eigenschaften in einem anonymen Typ, der von einer Abfrage erstellt wird, sind immer Haupteigenschaften. Wenn custs3 in der folgenden For Each-Schleife ausgeführt wird, ist das Ergebnis eine Auflistung von Instanzen eines anonymen Typs mit den beiden Haupteigenschaften Name und ID.

For Each selectedCust In custs3
    Console.WriteLine(selectedCust.ID & ": " & selectedCust.Name)
Next

Die von custs3 dargestellten Elemente in der Auflistung sind stark typisiert. Sie können IntelliSense verwenden, um durch die verfügbaren Eigenschaften zu navigieren und deren Typen zu überprüfen.

Weitere Informationen finden Sie unter Einführung in LINQ in Visual Basic.

Entscheiden, ob anonyme Typen verwendet werden sollen

Bevor Sie ein Objekt als Instanz einer anonymen Klasse erzeugen, überlegen Sie sich, ob dies die beste Wahl ist. Wenn Sie beispielsweise ein temporäres Objekt erstellen möchten, das verknüpfte Daten enthalten soll, und Sie keine weiteren Felder und Methoden benötigen, die in einer vollständigen Klasse normalerweise enthalten sind, ist ein anonymer Typ eine angemessene Lösung. Anonyme Typen sind auch nützlich, wenn jede Deklaration eine andere Auswahl von Eigenschaften enthalten soll oder die Reihenfolge der Eigenschaften geändert werden soll. Wenn Ihr Projekt jedoch mehrere Objekte mit den gleichen Eigenschaften in festgelegter Reihenfolge enthält, können sie unter Verwendung eines benannten Typs mit einem Klassenkonstruktor einfacher deklariert werden. Beispielsweise ist es einfacher, mehrere Instanzen einer Product-Klasse mit einem geeigneten Konstruktor zu deklarieren als mehrere Instanzen eines anonymen Typs.

' Declaring instances of a named type.
Dim firstProd1 As New Product("paperclips", 1.29)
Dim secondProd1 As New Product("desklamp", 28.99)
Dim thirdProd1 As New Product("stapler", 5.09)

' Declaring instances of an anonymous type.
Dim firstProd2 = New With {Key .Name = "paperclips", Key .Price = 1.29}
Dim secondProd2 = New With {Key .Name = "desklamp", Key .Price = 28.99}
Dim thirdProd2 = New With {Key .Name = "stapler", Key .Price = 5.09}

Ein weiterer Vorteil benannter Typen besteht darin, dass der Compiler versehentliche Schreibfehler bei einem Eigenschaftennamen erkennen kann. Im vorhergehenden Beispiel sollen firstProd2, secondProd2 und thirdProd2 Instanzen desselben anonymen Typs sein. Wenn Sie jedoch versehentlich thirdProd2 auf eine der folgenden Weisen deklariert hätten, würde sich sein Typ von dem von firstProd2 und secondProd2 unterscheiden.

' Dim thirdProd2 = New With {Key .Nmae = "stapler", Key .Price = 5.09}
' Dim thirdProd2 = New With {Key .Name = "stapler", Key .Price = "5.09"}
' Dim thirdProd2 = New With {Key .Name = "stapler", .Price = 5.09}

Bedeutender ist jedoch die Tatsache, dass es Beschränkungen bei der Verwendung von anonymen Typen gibt, die für Instanzen von benannten Typen nicht gelten. firstProd2, secondProd2 und thirdProd2 sind Instanzen desselben anonymen Typs. Der Name des gemeinsamen anonymen Typs ist jedoch nicht verfügbar und kann im Code an den Stellen, an denen ein Typname erwartet wird, nicht verwendet werden. Beispielsweise kann ein anonymer Typ nicht zur Definition einer Methodensignatur oder zur Deklaration einer anderen Variablen, eines anderen Felds oder eines Typs verwendet werden. Folglich sind anonyme Typen nicht geeignet, wenn Informationen von mehreren Methoden gemeinsam verwendet werden müssen.

Definition eines anonymen Typs

Als Reaktion auf die Deklaration einer Instanz eines anonymen Typs erzeugt der Compiler eine neue Klassendefinition, die die angegebenen Eigenschaften enthält.

Wenn der anonyme Typ mindestens eine Haupteigenschaft enthält, überschreibt die Definition drei von Object geerbte Member: Equals, GetHashCode und ToString. Der Code, der für das Testen auf Gleichheit und für die Ermittlung des Hashcodewerts erzeugt wird, berücksichtigt nur die Haupteigenschaften. Wenn der anonyme Typ keine Haupteigenschaften enthält, wird nur ToString überschrieben. Explizit benannte Eigenschaften eines anonymen Typs dürfen keine Konflikte mit diesen erzeugten Methoden hervorrufen. Das heißt, Sie können .Equals, .GetHashCode oder .ToString nicht verwenden, um eine Eigenschaft zu benennen.

Anonyme Typdefinitionen, die mindestens eine Haupteigenschaft enthalten, implementieren auch die System.IEquatable<T>-Schnittstelle, wobei T der Typ des anonymen Typs ist.

Weitere Informationen über den compilergenerierten Code und die Funktionalität der überschriebenen Methoden finden Sie unter Definition von anonymen Typen (Visual Basic).

Siehe auch

Aufgaben

Gewusst wie: Deklarieren einer Instanz eines anonymen Typs (Visual Basic)

Gewusst wie: Ableiten von Eigenschaftennamen und Typen in Deklarationen von anonymen Typen (Visual Basic)

Referenz

Key (Visual Basic)

Konzepte

Objektinitialisierer: Benannte und anonyme Typen (Visual Basic)

Lokaler Typrückschluss (Visual Basic)

Einführung in LINQ in Visual Basic

Benannte Typen im Vergleich zu anonymen Typen (Visual Basic)

Definition von anonymen Typen (Visual Basic)