Tipi anonimi

Aggiornamento: novembre 2007

Visual Basic 2008 introduce i tipi anonimi che consentono di creare oggetti senza scrivere una definizione della classe per il tipo di dati. La classe viene generata direttamente dal compilatore. La classe non ha un nome utilizzabile, eredita direttamente da Objecte contiene le proprietà specificate nella dichiarazione dell'oggetto. Perché il nome del tipo di dati non è specificato, viene considerato un tipo anonimo.

Nell'esempio riportato di seguito viene dichiarato e creato un oggetto product variabile come istanza di un tipo anonimo che ha due proprietà, Name e Price.

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

Una espressione di query utilizza tipi anonimi per combinare colonne di dati selezionate da una query. Non è possibile definire il tipo di risultato in anticipo, perché non è possibile prevedere quali colonne possono venire selezionate da una particolare query. I tipi anonimi consentono di scrivere una query che seleziona qualsiasi numero di colonne, in qualsiasi ordine. Il compilatore crea un tipo di dati che corrisponde alle proprietà specificate e all'ordine specificato.

Negli esempi riportati di seguito, products è un elenco di oggetti di prodotto ognuno dei quali che dispone di molte proprietà. Il namePriceQuery variabile contiene la definizione di una query che, quando viene eseguita, restituisce un insieme di istanze di un tipo anonimo che ha due proprietà, Name e Price.

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

Il nameQuantityQuery variabile contiene la definizione di una query che, quando viene eseguita, restituisce un insieme di istanze di un tipo anonimo che ha due proprietà, Name e OnHand.

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

Per le ulteriori informazioni sul codice creato dal compilatore per un tipo anonimo, vedere Definizione del tipo anonimo.

Attenzione:

Il nome del tipo anonimo viene generato dal compilatore e può variare da una compilazione a un'altra. Il codice non deve utilizzare o non deve basarsi sul nome di un tipo anonimo perché il nome potrebbe cambiare quando un progetto viene ricompilato.

Dichiarare un tipo anonimo

La dichiarazione di un'istanza di un tipo anonimo utilizza un elenco di inizializzatori per specificare le proprietà del tipo. Quando si dichiara un tipo anonimo e possibile specificare solo le proprietà , non altri elementi della classe come metodi o eventi. Nell'esempio riportato di seguito product1 è un'istanza di un tipo anonimo che ha due proprietà, Name e 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}

Se si definiscono le proprietà come proprietà chiave, è possibile utilizzarle per verificare l'uguaglianza di due istanze di tipo anonimo. Tuttavia, i valori delle proprietà chiave non possono essere modificati. Per ulteriori informazioni, vedere la sezione Proprietà chiave più avanti in questo argomento.

Si noti che dichiarare un'istanza di un tipo anonimo è come dichiarare un'istanza di un tipo denominato utilizzando un inizializzatore di oggetto:

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

Per un confronto più dettagliato di dichiarazioni di tipo denominati e anonimi, vedere Confronto tra tipi denominati e tipi anonimi.

Per ulteriori informazioni sulle altre modalità per specificare le proprietà di un tipo anonimo, vedere Procedura: dedurre nomi di proprietà e tipi nelle dichiarazioni di tipo anonimo.

Proprietà principali

Le proprietà chiave differiscono dalle proprietà non chiave in vari aspetti fondamentali:

  • Per determinare se due istanze sono uguali vengono confrontati solo i valori di proprietà chiave.

  • I valori delle proprietà chiave sono di sola lettura e non possono essere modificati.

  • Solo valori della proprietà chiave vengono inclusi nell'algoritmo di codice hash generato dal compilatore per un tipo anonimo.

Uguaglianza

Istanze di tipi anonimi possono essere uguali solo se sono istanze dello stesso tipo anonimo. Il compilatore considera due istanze come istanze dello stesso tipo se soddisfano le condizioni seguenti:

  • Sono dichiarate nello stesso assembly.

  • Le rispettive proprietà hanno gli stessi nomi, gli stessi tipi dedotti e vengono dichiarate nello stesso ordine. Nel confronto tra nomi non viene applicata la distinzione tra maiuscole e minuscole.

  • Vengono indicate come proprietà chiave le stesse proprietà di ognuna .

  • Almeno una proprietà in ogni dichiarazione è una proprietà chiave.

Un'istanza di tipi anonimi che non ha proprietà chiave è uguale solo a se stessa.

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

Due istanze di tipi anonimi sono uguali solo se i valori delle relative proprietà chiave sono uguali. Negli esempi riportati di seguito viene illustrato come viene verificata l'uguaglianza.

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

Valori di sola lettura.

I valori delle proprietà chiave non possono essere modificati. Nell'esempio descritto in precedenza, prod8 i campi Name e Price sono read-only, ma OnHand possono venire modificati.

' 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

Tipi anonimi dalle espressioni di query

Le espressioni di query non richiedono sempre la creazione di tipi anonimi. Quando è possibile, utilizzano un tipo esistente per contenere i dati della colonna. Questa situazione si verifica quando la query restituisce record interi dall'origine dati, oppure un unico campo da ogni record. Negli esempi di codice riportati di seguito, customers è un insieme di oggetti di una classe Customer. La classe dispone di molte proprietà ed è possibile includerne una o più nel risultato della query, in qualsiasi ordine. Nei primi due esempi, non viene richiesto alcun tipo anonimo, perché le query seleziona elementi di tipi denominati:

  • custs1 contiene un insieme di stringhe, perché cust.Name è una stringa.

    Dim custs1 = From cust In customers _
                 Select cust.Name
    
  • custs2 contiene un insieme di oggetti Customer, perché ogni elemento di customers è un oggetto Customer e la query seleziona l'intero elemento.

    Dim custs2 = From cust In customers _
                 Select cust
    

Tuttavia, non sempre sono disponibili tipi denominati adatti. Ad esempio, potrebbe essere necessario selezionare nomi e indirizzi del cliente per un certo scopo, numeri ID e locazioni del cliente per un altro scopo e nomi del cliente, indirizzi e cronologia dell'ordine per un terzo scopo. I tipi anonimi consentono di selezionare qualsiasi combinazione di proprietà, in qualsiasi ordine, senza prima dichiarare un nuovo tipo denominato per contenere il risultato. Invece, il compilatore crea un tipo anonimo per ogni compilazione di proprietà. Nella query seguente vengono selezionati solo il nome del cliente e il numero ID da ogni oggetto Customer in customers. Pertanto, il compilatore crea un tipo anonimo che contiene solo quelle due proprietà.

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

Sia i nomi che i tipi di dati delle proprietà nel tipo anonimo vengono forniti dagli argomenti a Select, cust.Name e cust.ID. Le proprietà in un tipo anonimo creato da una query sono sempre proprietà chiave. Quando custs3 viene eseguito nel seguente ciclo For Each, il risultato è un insieme di istanze di un tipo anonimo con due proprietà chiave, Name e ID.

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

Gli elementi nell'insieme rappresentato da custs3 sono fortemente tipizzati ed è possibile utilizzare IntelliSense per spostarsi tra le proprietà disponibili e verificarne i tipi.

Per ulteriori informazioni, vedere Introduzione a LINQ in Visual Basic.

Decidere se utilizzare tipi anonimi

Prima di creare un oggetto come un'istanza di una classe anonima, valutare qual è la migliore opzione. Ad esempio, se si desidera creare un oggetto temporaneo per contenere dati correlati e non sono necessari gli altri campi e metodi che una classe completa potrebbe contenere, un tipo anonimo è una buona soluzione. I tipi anonimi sono anche efficaci se si desidera una selezione diversa di proprietà per ogni dichiarazione, o se si vuole modificare l'ordine delle proprietà. Tuttavia, se il progetto include molti oggetti che hanno le stesse proprietà, in un ordine fisso, è possibile dichiararli più facilmente utilizzando un tipo denominato con un costruttore di classe. Ad esempio, con un costruttore adeguato, è più facile dichiarare molte istanze di una classe Product rispetto a dichiarare molte istanze di un tipo anonimo.

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

Un altro vantaggio dei tipi denominati è che il compilatore può intercettare un errore fortuito di digitazione di un nome della proprietà. Negli esempi precedenti, firstProd2, secondProd2e thirdProd2 devono essere istanze dello stesso tipo anonimo. Tuttavia, se si volesse dichiarare accidentalmente thirdProd2 in una delle modalità seguenti, il tipo sarebbe diverso da quello di firstProd2 e secondProd2.

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

Ancora più importante, esistono limitazioni sull'utilizzo dei tipi anonimi che non valgono per le istanze di tipi denominati. firstProd2, secondProd2, e thirdProd2 sono istanze dello stesso tipo anonimo. Tuttavia, il nome per il tipo anonimo condiviso non è disponibile e non può trovarsi nel codice dove è previsto un nome tipo. Ad esempio, un tipo anonimo non può essere utilizzato per definire una firma del metodo, per dichiarare un'altra variabile o un campo o in qualsiasi dichiarazione di tipo. Di conseguenza, i tipi anonimi non sono adatti quando è necessario condividere le informazioni tra i metodi.

Definizione di un tipo anonimo

In risposta alla dichiarazione di un'istanza di un tipo anonimo, il compilatore crea una nuova definizione di classe che contiene le proprietà specificate.

Se il tipo anonimo contiene almeno una proprietà chiave, la definizione esegue l'override di tre membri ereditati da Object: Equals, GetHashCodee ToString. Il codice prodotto per verificare l'uguaglianza e determinare il valore del codice hash considera solo le proprietà chiave. Se il tipo anonimo non contiene proprietà chiave, viene eseguito l'override solo di ToString. Le proprietà denominate in modo esplicito di un tipo anonimo non devono essere in conflitto con questi metodi generati. Ovvero, non è possibile utilizzare .Equals, .GetHashCode o .ToString per denominare una proprietà.

Le definizioni di tipo anonimo che includono almeno una proprietà chiave implementano anche l'interfaccia System.IEquatable<T>, dove T è il tipo del tipo anonimo.

Per le ulteriori informazioni sul codice creato dal compilatore e le funzionalità dei metodi per eseguire l'override, vedere Definizione del tipo anonimo.

Vedere anche

Attività

Procedura: dichiarare un'istanza di un tipo anonimo

Procedura: dedurre nomi di proprietà e tipi nelle dichiarazioni di tipo anonimo

Concetti

Inizializzatori di oggetto: tipi denominati e tipi anonimi

Inferenza dei tipi locali

Introduzione a LINQ in Visual Basic

Confronto tra tipi denominati e tipi anonimi

Definizione del tipo anonimo

Riferimenti

Key (Visual Basic)