Dela via


Anonyma typer (Visual Basic)

Visual Basic stöder anonyma typer som gör att du kan skapa objekt utan att skriva en klassdefinition för datatypen. I stället genererar kompilatorn en klass åt dig. Klassen har inget användbart namn, ärver direkt från Objectoch innehåller de egenskaper som du anger när objektet deklareras. Eftersom namnet på datatypen inte har angetts kallas det för en anonym typ.

I följande exempel deklareras och skapas variabeln product som en instans av en anonym typ som har två egenskaper och NamePrice.

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

Ett frågeuttryck använder anonyma typer för att kombinera kolumner med data som valts av en fråga. Du kan inte definiera typen av resultat i förväg eftersom du inte kan förutsäga vilka kolumner en viss fråga kan välja. Med anonyma typer kan du skriva en fråga som väljer valfritt antal kolumner i valfri ordning. Kompilatorn skapar en datatyp som matchar de angivna egenskaperna och den angivna ordningen.

I följande exempel products finns en lista över produktobjekt som var och en har många egenskaper. Variabeln namePriceQuery innehåller definitionen av en fråga som när den körs returnerar en samling instanser av en anonym typ som har två egenskaper och NamePrice.

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

Variabeln nameQuantityQuery innehåller definitionen av en fråga som när den körs returnerar en samling instanser av en anonym typ som har två egenskaper och NameOnHand.

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

Mer information om koden som skapats av kompilatorn för en anonym typ finns i Definition av anonym typ.

Varning

Namnet på den anonyma typen genereras av kompilatorn och kan variera från kompilering till kompilering. Koden ska inte använda eller förlita sig på namnet på en anonym typ eftersom namnet kan ändras när ett projekt omkompileras.

Deklarera en anonym typ

Deklarationen av en instans av en anonym typ använder en initialiserarlista för att ange egenskaperna för typen. Du kan bara ange egenskaper när du deklarerar en anonym typ, inte andra klasselement, till exempel metoder eller händelser. I följande exempel product1 är en instans av en anonym typ som har två egenskaper: Name och 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}

Om du anger egenskaper som nyckelegenskaper kan du använda dem för att jämföra två anonyma typinstanser för likhet. Det går dock inte att ändra värdena för viktiga egenskaper. Mer information finns i avsnittet Nyckelegenskaper senare i det här avsnittet.

Observera att deklarera en instans av en anonym typ är som att deklarera en instans av en namngiven typ med hjälp av en objektinitierare:

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

Mer information om andra sätt att ange egenskaper för anonym typ finns i Så här gör du: Härleda egenskapsnamn och typer i anonyma typdeklarationer.

Nyckelegenskaper

Viktiga egenskaper skiljer sig från icke-nyckelegenskaper på flera grundläggande sätt:

  • Endast värdena för nyckelegenskaper jämförs för att avgöra om två instanser är lika.

  • Värdena för nyckelegenskaper är skrivskyddade och kan inte ändras.

  • Endast nyckelegenskapsvärden ingår i den kompilatorgenererade hashkodalgoritmen för en anonym typ.

Tillämplig

Instanser av anonyma typer kan bara vara lika med om de är instanser av samma anonyma typ. Kompilatorn behandlar två instanser som instanser av samma typ om de uppfyller följande villkor:

  • De deklareras i samma sammansättning.

  • Deras egenskaper har samma namn, samma härledda typer, och deklareras i samma ordning. Namnjämförelser är inte skiftlägeskänsliga.

  • Samma egenskaper i var och en markeras som nyckelegenskaper.

  • Minst en egenskap i varje deklaration är en nyckelegenskap.

En instans av anonyma typer som inte har några nyckelegenskaper är lika med sig själv.

' 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))

Två instanser av samma anonyma typ är lika med om värdena för deras nyckelegenskaper är lika med. Följande exempel illustrerar hur likhet testas.

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))

Skrivskyddade värden

Det går inte att ändra värdena för viktiga egenskaper. I prod8 föregående exempel är read-onlytill exempel fälten Name och Price , men OnHand kan ändras.

' 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

Anonyma typer från frågeuttryck

Frågeuttryck kräver inte alltid att anonyma typer skapas. När det är möjligt använder de en befintlig typ för att lagra kolumndata. Detta inträffar när frågan returnerar antingen hela poster från datakällan eller bara ett fält från varje post. I följande kodexempel customers är en samling objekt i en Customer klass. Klassen har många egenskaper och du kan inkludera en eller flera av dem i frågeresultatet i valfri ordning. I de två första exemplen krävs inga anonyma typer eftersom frågorna väljer element av namngivna typer:

  • custs1 innehåller en samling strängar, eftersom cust.Name det är en sträng.

    Dim custs1 = From cust In customers
                 Select cust.Name
    
  • custs2 innehåller en samling Customer objekt, eftersom varje element customers i är ett Customer objekt och hela elementet väljs av frågan.

    Dim custs2 = From cust In customers
                 Select cust
    

Lämpliga namngivna typer är dock inte alltid tillgängliga. Du kanske vill välja kundnamn och adresser för ett syfte, kund-ID-nummer och platser för ett annat, samt kundnamn, adresser och orderhistorik för en tredje. Med anonyma typer kan du välja valfri kombination av egenskaper, i valfri ordning, utan att först deklarera en ny namngiven typ som innehåller resultatet. I stället skapar kompilatorn en anonym typ för varje kompilering av egenskaper. Följande fråga väljer endast kundens namn och ID-nummer från varje Customer objekt i customers. Kompilatorn skapar därför en anonym typ som endast innehåller dessa två egenskaper.

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

Både namnen och datatyperna för egenskaperna i den anonyma typen tas från argumenten till Selectoch cust.Namecust.ID. Egenskaperna i en anonym typ som skapas av en fråga är alltid viktiga egenskaper. När custs3 körs i följande For Each loop är resultatet en samling instanser av en anonym typ med två nyckelegenskaper Name och ID.

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

Elementen i samlingen som representeras av custs3 skrivs starkt och du kan använda IntelliSense för att navigera genom de tillgängliga egenskaperna och verifiera deras typer.

Mer information finns i Introduktion till LINQ i Visual Basic.

Bestämma om anonyma typer ska användas

Innan du skapar ett objekt som en instans av en anonym klass bör du överväga om det är det bästa alternativet. Om du till exempel vill skapa ett tillfälligt objekt som ska innehålla relaterade data och du inte behöver andra fält och metoder som en fullständig klass kan innehålla, är en anonym typ en bra lösning. Anonyma typer är också praktiska om du vill ha olika egenskaper för varje deklaration, eller om du vill ändra ordningen på egenskaperna. Men om projektet innehåller flera objekt som har samma egenskaper kan du i en fast ordning deklarera dem enklare genom att använda en namngiven typ med en klasskonstruktor. Med en lämplig konstruktor är det till exempel enklare att deklarera flera instanser av en Product klass än att deklarera flera instanser av en anonym typ.

' 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}

En annan fördel med namngivna typer är att kompilatorn kan fånga en oavsiktlig feltypning av ett egenskapsnamn. I föregående exempel firstProd2är , secondProd2och thirdProd2 avsedda att vara instanser av samma anonyma typ. Men om du av misstag deklarerar thirdProd2 på något av följande sätt skulle dess typ skilja sig från firstProd2 och secondProd2.

' 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}

Ännu viktigare är att det finns begränsningar för användningen av anonyma typer som inte gäller för instanser av namngivna typer. firstProd2, secondProd2och thirdProd2 är instanser av samma anonyma typ. Namnet på den delade anonyma typen är dock inte tillgängligt och kan inte visas där ett typnamn förväntas i koden. En anonym typ kan till exempel inte användas för att definiera en metodsignatur, deklarera en annan variabel eller ett annat fält eller i någon typdeklaration. Därför är anonyma typer inte lämpliga när du måste dela information mellan olika metoder.

En definition av anonym typ

Som svar på deklarationen av en instans av en anonym typ skapar kompilatorn en ny klassdefinition som innehåller de angivna egenskaperna.

Om den anonyma typen innehåller minst en nyckelegenskap åsidosätter definitionen tre medlemmar som ärvts från Object: Equals, GetHashCodeoch ToString. Koden som skapas för att testa likhet och bestämma hash-kodvärdet tar endast hänsyn till nyckelegenskaperna. Om den anonyma typen inte innehåller några nyckelegenskaper åsidosättas bara ToString . Explicit namngivna egenskaper av en anonym typ kan inte vara i konflikt med dessa genererade metoder. Du kan alltså inte använda .Equals, .GetHashCodeeller .ToString för att namnge en egenskap.

Anonyma typdefinitioner som har minst en nyckelegenskap implementerar System.IEquatable<T> också gränssnittet, där T är typen av anonym typ.

Mer information om koden som skapats av kompilatorn och funktionerna i de åsidosatta metoderna finns i Definition av anonym typ.

Se även