Inizializzatori di oggetto: tipi denominati e tipi anonimi (Visual Basic)

Gli inizializzatori di oggetti consentono di specificare le proprietà per un oggetto complesso usando una singola espressione. Possono essere usati per creare istanze di tipi denominati e di tipi anonimi.

Dichiarazioni

Le dichiarazioni di istanze di tipi denominati e anonimi possono sembrare quasi identiche, ma i relativi effetti non sono uguali. Ogni categoria ha capacità e restrizioni specifiche. Nell'esempio seguente viene illustrato un modo pratico per dichiarare e inizializzare un'istanza di una classe denominata, Customer, usando un elenco di inizializzatori di oggetti. Si noti che il nome della classe viene specificato dopo la parola chiave New.

Dim namedCust = New Customer With {.Name = "Terry Adams"}

Un tipo anonimo non ha un nome utilizzabile, pertanto una creazione di istanze di un tipo anonimo non può includere un nome di classe.

Dim anonymousCust = New With {.Name = "Hugo Garcia"}

I requisiti e i risultati delle due dichiarazioni non sono uguali. Per namedCust, deve esistere già una classe Customer con una proprietà Name e la dichiarazione crea un'istanza di tale classe. Per anonymousCust, il compilatore definisce una nuova classe con una proprietà, una stringa denominata Name, e crea una nuova istanza di tale classe.

Tipi denominati

Gli inizializzatori di oggetti consentono di chiamare con facilità il costruttore di un tipo e quindi impostare i valori di alcune o tutte le proprietà in una singola istruzione. Il compilatore richiama il costruttore appropriato per l'istruzione: il costruttore senza parametri, se non vengono presentati argomenti, o un costruttore con parametri, se vengono inviati uno o più argomenti. Successivamente, le proprietà specificate vengono inizializzate nell'ordine in cui vengono presentate nell'elenco di inizializzatori.

Ogni inizializzazione nell'elenco di inizializzatori è costituita dall'assegnazione di un valore iniziale a un membro della classe. I nomi e i tipi di dati dei membri vengono determinati quando viene definita la classe. Negli esempi seguenti la classe Customer deve esistere e deve avere membri denominati Name e City che possono accettare valori stringa.

Dim cust0 As Customer = New Customer With {.Name = "Toni Poe", 
                                           .City = "Louisville"}

In alternativa, è possibile ottenere lo stesso risultato usando il codice seguente:

Dim cust1 As New Customer With {.Name = "Toni Poe", 
                                .City = "Louisville"}

Ognuna di queste dichiarazioni equivale all'esempio seguente, che crea un oggetto Customer usando il costruttore senza parametri e quindi specifica i valori iniziali per le proprietà Name e City usando un'istruzione With.

Dim cust2 As New Customer()
With cust2
    .Name = "Toni Poe"
    .City = "Louisville"
End With

Se la classe Customer contiene un costruttore con parametri che consente di inviare un valore per Name, ad esempio, è anche possibile dichiarare e inizializzare un oggetto Customer nei modi seguenti:

Dim cust3 As Customer = 
    New Customer("Toni Poe") With {.City = "Louisville"}
' --or--
Dim cust4 As New Customer("Toni Poe") With {.City = "Louisville"}

Non è necessario inizializzare tutte le proprietà, come illustrato nel codice seguente.

Dim cust5 As Customer = New Customer With {.Name = "Toni Poe"}

L'elenco di inizializzazione non può tuttavia essere vuoto. Le proprietà non inizializzate mantengono i valori predefiniti.

Inferenza del tipo con tipi denominati

È possibile abbreviare il codice per la dichiarazione di cust1 combinando gli inizializzatori di oggetti e l'inferenza del tipo locale. In questo modo è possibile omettere la clausola As nella dichiarazione di variabile. Il tipo di dati della variabile viene dedotto dal tipo dell'oggetto creato dall'assegnazione. Nell'esempio seguente il tipo di cust6 è Customer.

Dim cust6 = New Customer With {.Name = "Toni Poe", 
                               .City = "Louisville"}

Osservazioni sui tipi denominati

  • Un membro della classe non può essere inizializzato più di una volta nell'elenco di inizializzatori di oggetti. La dichiarazione di cust7 provoca un errore.

    '' This code does not compile because Name is initialized twice.
    ' Dim cust7 = New Customer With {.Name = "Toni Poe", 
    '                                .City = "Louisville",
    '                                .Name = "Blue Yonder Airlines"}
    
  • Un membro può essere utilizzato per inizializzare se stesso o un altro campo. Se si accede a un membro prima dell'inizializzazione, come nella dichiarazione seguente per cust8, verrà usato il valore predefinito. Tenere presente che quando viene elaborata una dichiarazione che usa un inizializzatore di oggetto, viene prima di tutto richiamato il costruttore appropriato. Successivamente vengono inizializzati i singoli campi nell'elenco di inizializzatori. Negli esempi seguenti il valore predefinito per Name viene assegnato per cust8 e un valore inizializzato viene assegnato in cust9.

    Dim cust8 = New Customer With {.Name = .Name & ", President"}
    Dim cust9 = New Customer With {.Name = "Toni Poe", 
                                   .Title = .Name & ", President"}
    

    Nell'esempio seguente viene usato il costruttore con parametri da cust3 e cust4 per dichiarare e inizializzare cust10 e cust11.

    Dim cust10 = New Customer("Toni Poe") With {.Name = .Name & ", President"}
    ' --or--
    Dim cust11 As New Customer("Toni Poe") With {.Name = .Name & ", President"}
    
  • Gli inizializzatori di oggetti possono essere annidati. Nell'esempio seguente AddressClass è una classe con due proprietà, City e State, e la classe Customer ha una proprietà Address che è un'istanza di AddressClass.

    Dim cust12 = 
        New Customer With {.Name = "Toni Poe", 
                           .Address = 
                               New AddressClass With {.City = "Louisville", 
                                                      .State = "Kentucky"}}
    Console.WriteLine(cust12.Address.State)
    
  • L'elenco di inizializzazione non può essere vuoto.

  • L'istanza in fase di inizializzazione non può essere di tipo Object.

  • I membri della classe in fase di inizializzazione non possono essere membri condivisi, membri di sola lettura, costanti o chiamate al metodo.

  • I membri della classe in fase di inizializzazione non possono essere indicizzati o qualificati. Gli esempi seguenti generano errori del compilatore:

    '' Not valid.

    ' Dim c1 = New Customer With {.OrderNumbers(0) = 148662}

    ' Dim c2 = New Customer with {.Address.City = "Springfield"}

Tipi anonimi

I tipi anonimi usano gli inizializzatori di oggetti per creare istanze di nuovi tipi che non vengono definiti e denominati in modo esplicito. Il compilatore genera invece un tipo in base alle proprietà designate nell'elenco di inizializzatori di oggetti. Poiché il nome del tipo non viene specificato, viene definito tipo anonimo. Ad esempio, confrontare la dichiarazione seguente con quella precedente per cust6.

Dim cust13 = New With {.Name = "Toni Poe", 
                       .City = "Louisville"}

L'unica differenza a livello sintattico è che non viene specificato alcun nome dopo New per il tipo di dati. Tuttavia, ciò che accade è piuttosto diverso. Il compilatore definisce un nuovo tipo anonimo con due proprietà, Name e City, e ne crea un'istanza con i valori specificati. L'inferenza del tipo determina che Name e City nell'esempio sono di tipo stringa.

Attenzione

Il nome del tipo anonimo viene generato dal compilatore e può variare da compilazione a compilazione. Il codice non deve usare o basarsi sul nome di un tipo anonimo.

Poiché il nome del tipo non è disponibile, non è possibile usare una clausola As per dichiarare cust13. Il tipo deve essere dedotto. Senza usare l'associazione tardiva, questo limita l'uso di tipi anonimi alle variabili locali.

I tipi anonimi forniscono supporto critico per le query LINQ. Per altre informazioni sull'uso di tipi anonimi nelle query, vedere Tipi anonimi e Introduzione a LINQ in Visual Basic.

Osservazioni sui tipi anonimi

  • In genere, tutte o quasi tutte le proprietà in una dichiarazione di tipo anonimo saranno proprietà chiave, indicate digitando la parola chiave Key davanti al nome della proprietà.

    
    Dim anonymousCust1 = New With {Key .Name = "Hugo Garcia", 
                                   Key .City = "Louisville"}
    

    Per altre informazioni sulle proprietà chiave, vedere Key.

  • Analogamente ai tipi denominati, gli elenchi di inizializzatori per le definizioni di tipi anonimi devono dichiarare almeno una proprietà.

    Dim anonymousCust = New With {.Name = "Hugo Garcia"}
    
  • Quando viene dichiarata un'istanza di un tipo anonimo, il compilatore genera una definizione di tipo anonimo corrispondente. I nomi e i tipi di dati delle proprietà vengono ricavati dalla dichiarazione di istanza e vengono inclusi dal compilatore nella definizione. Le proprietà non sono denominate e definite in anticipo, come avviene per un tipo denominato. I relativi tipi vengono dedotti. Non è possibile specificare i tipi di dati delle proprietà usando una clausola As.

  • I tipi anonimi possono anche stabilire i nomi e i valori delle relative proprietà in diversi altri modi. Ad esempio, una proprietà di tipo anonimo può accettare sia il nome sia il valore di una variabile oppure il nome e il valore di una proprietà di un altro oggetto.

    ' Create a variable, Name, and give it an initial value.
    Dim Name = "Hugo Garcia"
    
    ' Variable anonymousCust2 will have one property, Name, with 
    ' "Hugo Garcia" as its initial value.
    Dim anonymousCust2 = New With {Key Name}
    
    ' The next declaration uses a property from namedCust, defined
    ' in an earlier example. After the declaration, anonymousCust3 will
    ' have one property, Name, with "Terry Adams" as its value.
    Dim anonymousCust3 = New With {Key namedCust.Name}
    

    Per altre informazioni sulle opzioni per la definizione delle proprietà nei tipi anonimi, vedere Procedura: Dedurre nomi e tipi di proprietà nelle dichiarazioni di tipi anonimi.

Vedi anche