2015-01-21 11 views
12

Ho letto che:Inizializzatore raccolta C# 6 - Chiarificazione?

Il team sono in genere stati impegnati nell'attuazione di altre variazioni sul inizializzatori. Per esempio ora è possibile inizializzare un oggetto Dictionary

Ma guardando:

var Dic = new Dictionary<string,int>{ {"x",3}, {"y",7} }; 

VS

var Dic = new Dictionary<string,int>{ ["x"]=3, ["y"]=7 }; 

Non vedo dove il beneficio è. sembra uguale. Entrambi non sono altro che una raccolta di valori nominali.
si scambiano di coppie di parentesi graffe per coppie di parentesi quadre e alcune virgole

Domanda:

Qual è il valore aggiunto per l'utilizzo della nuova sintassi? un esempio del mondo reale sarebbe molto apprezzato.

+2

v'è alcun beneficio. Sembra solo più nodoso. –

+1

@TravisJ Trovo questo molto strano ("nessun vantaggio ..."), be 'il '$ xxx' è bello, ma pensare che sono appena cambiati da parentesi graffe a parentesi ...? –

+1

È solo una variazione. Suppongo che il vantaggio, se ce ne sia qualcuno, potrebbe essere migliore per le persone con differenti background di programmazione. Ma a parte questo, in realtà non cambia la funzionalità di un dizionario, né gli permette di avere una sorta di nuovi poteri magici :) –

risposta

20

Il vantaggio principale qui con un dizionario è la coerenza. Con un dizionario, l'inizializzazione non era uguale all'utilizzo.

Per esempio, si potrebbe fare:

var dict = new Dictionary<int,string>(); 
dict[3] = "foo"; 
dict[42] = "bar"; 

Ma utilizzando la sintassi di inizializzazione, si doveva usare le parentesi:

var dict = new Dictionary<int,string> 
{ 
    {3, "foo"}, 
    {42, "bar"} 
}; 

Il nuovo C# 6 indice sintassi di inizializzazione rende la sintassi di inizializzazione più coerente con l'indice utilizzo:

var dict = new Dictionary<int,string> 
{ 
    [3] = "foo", 
    [42] = "bar" 
}; 

Tuttavia, un vantaggio maggiore è che questo sy ntax offre anche il vantaggio di consentire l'inizializzazione di altri tipi. Qualsiasi tipo con un indicizzatore consentirà l'inizializzazione tramite questa sintassi, in cui i vecchi inizializzatori di raccolta funzionano solo con i tipi che implementano IEnumerable<T> e hanno un metodo Add. È successo con un Dictionary<TKey,TValue>, ma ciò non significa che abbia funzionato con qualsiasi tipo di indice.

+2

Reed, abit offtopic, ma ancora correlato - Ho anche visto (in un video, proprio ora) che C# 6 cerca anche il metodo Add, oltre al metodo instance, voglio dire che potrebbe essere in un metodo di estensione. quindi se qualcuno ha un metodo chiamato 'Insert', non sarai in grado di fare' new MyIenumerableType <> {{..., ...}, {..., ...}} 'perché è il tipo non ha il metodo 'Aggiungi'. ma C# 6 cercherà il 'Aggiungi' anche come metodo di estensione. (se non si ha il controllo del codice) –

+1

@RoyiNamir: passo brevemente i metodi di aggiunta dell'estensione in [questa risposta] (http://stackoverflow.com/a/27455822/390278).Questa aggiunta apre la porta per rendere il lavoro con le collezioni molto più fantastiche. –

+1

@RoyiNamir Sì, ma richiede ancora 'IEnumerable ', per cui è meno limitato, ma ancora un po 'limitato. –

9

Il codice nel primo caso utilizza la sintassi di inizializzazione della raccolta. Per essere in grado di utilizzare la sintassi raccolta inizializzatore, un must classe:

Collection Initializers:

  1. Implementare l'interfaccia IEnumerable.
  2. Definire un metodo accessibile Add(). (Come C# 6/VS2015, può essere un metodo di estensione)

Quindi una classe definita in questo modo possono utilizzare la sintassi:

public class CollectionInitializable : IEnumerable 
{ 
    public void Add(int value) { ... } 
    public void Add(string key, int value) { ... } 
    public IEnumerator GetEnumerator() { ... } 
} 

var obj = new CollectionInitializable 
{ 
    1, 
    { "two", 3 }, 
}; 

non tutti gli oggetti sono IEnumerable o ha un metodo add e quindi non può usare quella sintassi.


D'altra parte, molti oggetti definiscono (impostabili) gli indicizzatori. È qui che viene utilizzato l'inizializzatore dicionario. Potrebbe avere senso avere indici, ma non necessariamente IEnumerable. Con l'inizializzatore del dizionario, non è necessario essere IEnumerable, non è necessario un metodo Add(), è necessario solo un indicizzatore.

Essere in grado di inizializzare completamente un oggetto in una singola espressione è generalmente utile (e in alcuni contesti, un requisito). La sintassi dell'inizializzatore del dizionario rende più semplice farlo senza i requisiti elevati dell'utilizzo degli inizializzatori di raccolta.

3

Non ci sono vantaggi tecnici di per sé; è solo zucchero sintattico (come molte delle nuove funzionalità di C# 6). Il C# feature descriptions PDF, infatti, menziona solo questione di eleganza:

oggetto e raccolta inizializzatori sono utili per inizializzare dichiarativo campi e proprietà di oggetti, o dare una raccolta una prima serie di elementi. L'inizializzazione di dizionari e altri oggetti con gli indicizzatori è meno elegante. Stiamo aggiungendo una nuova sintassi di opporsi inizializzatori che consente di impostare i valori per le chiavi attraverso qualsiasi indicizzatore che il nuovo oggetto ha

+0

C'è un vantaggio, non si otterrà l'ArgumentException "Un elemento con la stessa chiave è già stato aggiunto." se si sta utilizzando la sintassi di inizializzazione dell'indice. Che è utile se cloni il tuo dizionario, quindi modifica alcuni valori che potrebbero o non sono già presenti. – Finickyflame

+0

@Finickyflame che era già possibile con la sintassi pre-C# 6 (al contrario di chiamare '.Add()'). – Gigi

4

Può essere una caratteristica discutibile, ma la nuova sintassi consente di impostare gli stessi più volte.

 private static Dictionary<string, string> test1 
     = new Dictionary<string, string>() { 
      ["a"] = "b", 
      ["a"] = "c" 
     }; 

è permesso: qui la chiave "a" ha il valore "c".

Al contrario, utilizzando

private static Dictionary<string, string> test2 
    = new Dictionary<string, string>() { 
     { "a","b" }, 
     { "a","c" }, 
    }; 

crea un'eccezione:

Unbehandelte Ausnahme: System.TypeInitializationException: Der Typeninitialisierer für "ConsoleApplication1.Program" hat eine Ausnahme verursacht. 
---> System.ArgumentException: Ein Element mit dem gleichen Schlüssel wurde bereits hinzugefügt. 
    bei System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) 
    bei System.Collections.Generic.Dictionary``2.Insert(TKey key, TValue value, Boolean add) 
    bei System.Collections.Generic.Dictionary``2.Add(TKey key, TValue value) 
    bei ConsoleApplication1.Program..cctor() in Program.cs:Zeile 19. 
    --- Ende der internen Ausnahmestapelüberwachung --- 
    bei ConsoleApplication1.Program.Main(String[] args) 
Problemi correlati