Freigeben über


Anonyme Typen (Visual Basic)

Visual Basic unterstützt anonyme Typen, mit denen Sie Objekte erstellen können, ohne eine Klassendefinition für den Datentyp zu schreiben. Stattdessen generiert der Compiler eine Klasse für Sie. Die Klasse hat keinen verwendbaren Namen, erbt direkt von Object, und enthält die Eigenschaften, die Sie beim Deklarieren des Objekts angeben. Da der Name des Datentyps nicht angegeben ist, wird er als anonymer Typ bezeichnet.

Im folgenden Beispiel wird die Variable product als Instanz eines anonymen Typs deklariert und erstellt, die zwei Eigenschaften aufweist, Name und Price.

' 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 Datenspalten zu kombinieren, die von einer Abfrage ausgewählt wurden. Sie können den Typ des Ergebnisses im Voraus nicht definieren, da Sie die Spalten, die eine bestimmte Abfrage auswählen kann, nicht vorhersagen können. Mit anonymen Typen können Sie eine Abfrage schreiben, die eine beliebige Anzahl von Spalten in beliebiger Reihenfolge auswählt. Der Compiler erstellt einen Datentyp, der den angegebenen Eigenschaften und der angegebenen Reihenfolge entspricht.

In den folgenden Beispielen products handelt es sich um eine Liste von Produktobjekten, die jeweils über viele Eigenschaften verfügen. Variable namePriceQuery enthält die Definition einer Abfrage, die, wenn sie ausgeführt wird, eine Auflistung von Instanzen eines anonymen Typs zurückgibt, die zwei Eigenschaften aufweisen, Name und Price.

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

Variable nameQuantityQuery enthält die Definition einer Abfrage, die, wenn sie ausgeführt wird, eine Auflistung von Instanzen eines anonymen Typs zurückgibt, die zwei Eigenschaften aufweisen, Name und OnHand.

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

Weitere Informationen zum vom Compiler für einen anonymen Typ erstellten Code finden Sie unter "Definition des anonymen Typs".

Vorsicht

Der Name des anonymen Typs wird vom Compiler generiert und kann von Kompilierung zu Kompilierung variieren. Ihr Code sollte nicht den Namen eines anonymen Typs verwenden oder sich darauf verlassen, da sich der Name ändern kann, wenn ein Projekt neu kompiliert wird.

Deklarieren eines anonymen Typs

Die Deklaration einer Instanz eines anonymen Typs verwendet eine Initialisierungsliste, um die Eigenschaften des Typs anzugeben. Sie können nur Eigenschaften angeben, wenn Sie einen anonymen Typ deklarieren, nicht andere Klassenelemente wie Methoden oder Ereignisse. Im folgenden Beispiel product1 handelt es sich um 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 Schlüsseleigenschaften festlegen, können Sie sie verwenden, um zwei anonyme Typinstanzen für Gleichheit zu vergleichen. Die Werte der Schlüsseleigenschaften können jedoch nicht geändert werden. Weitere Informationen finden Sie im Abschnitt "Wichtige Eigenschaften" weiter unten in diesem Thema.

Beachten Sie, dass das Deklarieren einer Instanz eines anonymen Typs wie das Deklarieren einer Instanz eines benannten Typs mithilfe eines Objektinitialisierungsprogramms ist:

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

Weitere Informationen zu anderen Methoden zum Angeben von Eigenschaften für anonyme Typen finden Sie unter How to: Infer Property Names and Types in Anonymous Type Declarations.

Schlüsseleigenschaften

Wichtige Eigenschaften unterscheiden sich auf verschiedene grundlegende Weise von Nicht-Schlüsseleigenschaften:

  • Es werden nur die Werte der Schlüsseleigenschaften verglichen, um festzustellen, ob zwei Instanzen gleich sind.

  • Die Werte der Schlüsseleigenschaften sind nur-lesbar und können nicht geändert werden.

  • Nur wichtige Eigenschaftswerte sind im vom Compiler generierten Hashcodealgorithmus für einen anonymen Typ enthalten.

Gleichheit

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

  • Sie werden in derselben Assembly deklariert.

  • Ihre Eigenschaften haben dieselben Namen, dieselben abgeleiteten Typen und werden in derselben Reihenfolge deklariert. Bei Namensvergleichen wird die Groß-/Kleinschreibung nicht beachtet.

  • Die gleichen Eigenschaften werden jeweils als Schlüsseleigenschaften markiert.

  • Mindestens eine Eigenschaft in jeder Deklaration ist eine Schlüsseleigenschaft.

Eine Instanz eines anonymen Typs, der keine Schlüsseleigenschaften aufweist, ist nur für sich selbst gleich.

' 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 Schlüsseleigenschaften gleich sind. Die folgenden Beispiele veranschaulichen, wie die 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))

Read-Only Werte

Die Werte der Schlüsseleigenschaften können nicht geändert werden. In prod8 im vorherigen Beispiel sind die Felder Name und Priceread-only, aber OnHand kann 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 von Abfrageausdrücken

Abfrageausdrücke erfordern nicht immer die Erstellung anonymer Typen. Wenn möglich, verwenden sie einen vorhandenen Typ, um die Spaltendaten zu enthalten. Dies tritt auf, wenn die Abfrage entweder ganze Datensätze aus der Datenquelle oder nur ein Feld aus jedem Datensatz zurückgibt. In den folgenden Codebeispielen customers handelt es sich um eine Auflistung von Objekten einer Customer Klasse. Die Klasse verfügt über viele Eigenschaften, und Sie können eine oder mehrere davon in das Abfrageergebnis in beliebiger Reihenfolge einschließen. In den ersten beiden Beispielen sind keine anonymen Typen erforderlich, da die Abfragen Elemente benannter Typen auswählen:

  • custs1 enthält eine Auflistung von Zeichenfolgen, da es sich um cust.Name eine Zeichenfolge handelt.

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

    Dim custs2 = From cust In customers
                 Select cust
    

Entsprechende benannte Typen sind jedoch nicht immer verfügbar. Möglicherweise möchten Sie Kundennamen und -adressen für einen Zweck, Kunden-ID-Nummern und Standorte für einen anderen sowie Kundennamen, Adressen und Bestellhistorien für ein Drittes auswählen. Anonyme Typen ermöglichen es Ihnen, eine beliebige Kombination von Eigenschaften in beliebiger Reihenfolge auszuwählen, ohne zuerst einen neuen benannten Typ zu deklarieren, um das Ergebnis zu enthalten. Stattdessen erstellt der Compiler für jede Zusammenstellung von Eigenschaften einen anonymen Typ. Die folgende Abfrage wählt nur den Namen und die ID-Nummer des Kunden aus jedem Customer Objekt aus customers. 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 im anonymen Typ werden aus den Argumenten von Select, cust.Name und cust.ID übernommen. Die Eigenschaften in einem anonymen Typ, der von einer Abfrage erstellt wird, sind immer wichtige Eigenschaften. Wenn custs3 in der folgenden For Each Schleife ausgeführt wird, ist das Ergebnis eine Sammlung von Instanzen eines anonymen Typs mit zwei Schlüsseleigenschaften Name und ID.

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

Die Elemente in der Auflistung, die durch custs3 dargestellt werden, 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 erstellen, überlegen Sie, ob dies die beste Option ist. Wenn Sie z. B. ein temporäres Objekt erstellen möchten, das verwandte Daten enthält, und Sie keine Notwendigkeit für andere Felder und Methoden haben, die eine vollständige Klasse enthalten kann, ist ein anonymer Typ eine gute Lösung. Anonyme Typen sind auch praktisch, wenn Sie für jede Deklaration eine andere Auswahl von Eigenschaften wünschen oder wenn Sie die Reihenfolge der Eigenschaften ändern möchten. Wenn Ihr Projekt jedoch mehrere Objekte mit den gleichen Eigenschaften enthält, können Sie sie einfacher deklarieren, indem Sie einen benannten Typ mit einem Klassenkonstruktor verwenden. Beispielsweise ist es mit einem geeigneten Konstruktor einfacher, mehrere Instanzen einer Product Klasse zu deklarieren, als mehrere Instanzen eines anonymen Typs zu deklarieren.

' 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 eine versehentliche Fehleingabe eines Eigenschaftsnamens abfangen kann. In den vorherigen Beispielen sind firstProd2, secondProd2 und thirdProd2 als Instanzen desselben anonymen Typs gedacht. Wenn Sie jedoch versehentlich thirdProd2 auf eine der folgenden Arten deklarieren würden, würde sich dessen Typ von dem von firstProd2 und secondProd2 unterscheiden.

' Dim thirdProd2 = New With {Key .Name = "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}

Wichtiger ist, dass es Einschränkungen bei der Verwendung anonymer Typen gibt, die nicht für Instanzen von benannten Typen gelten. firstProd2, secondProd2und thirdProd2 sind Instanzen desselben anonymen Typs. Der Name für den freigegebenen anonymen Typ ist jedoch nicht verfügbar und kann nicht angezeigt werden, wo ein Typname in Ihrem Code erwartet wird. Beispielsweise kann ein anonymer Typ nicht verwendet werden, um eine Methodensignatur zu definieren, eine andere Variable oder ein anderes Feld oder in einer Typdeklaration zu deklarieren. Daher sind anonyme Typen nicht geeignet, wenn Sie Informationen über Methoden hinweg freigeben müssen.

Anonyme Typdefinition

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

Wenn der anonyme Typ mindestens eine Schlüsseleigenschaft enthält, überschreibt die Definition drei Elemente, die von Object geerbt wurden: Equals, GetHashCode und ToString. Der zum Testen der Gleichheit erstellte Code und die Bestimmung des Hashcodewerts berücksichtigt nur die Schlüsseleigenschaften. Wenn der anonyme Typ keine Schlüsseleigenschaften enthält, wird nur ToString überschrieben. Explizit benannte Eigenschaften eines anonymen Typs können nicht mit diesen generierten Methoden in Konflikt geraten. Das heißt, Sie können .Equals, .GetHashCode oder .ToString nicht verwenden, um eine Eigenschaft zu benennen.

Anonyme Typdefinitionen mit mindestens einer Schlüsseleigenschaft implementieren auch die System.IEquatable<T> Schnittstelle, wobei T der Typ des anonymen Typs ist.

Weitere Informationen zum vom Compiler erstellten Code und zur Funktionalität der überschriebenen Methoden finden Sie unter Anonyme Typdefinition.

Siehe auch