2012-04-12 13 views
6

Vengo da JavaScript e so che { } è un oggetto letterale, che non richiede la chiamata new Object; Mi chiedo se è lo stesso con C# nella parte {"id",id}, {"saveChangesError",true}.Quale caratteristica C# consente l'uso di una notazione di tipo "oggetto letterale"?

So che ci sono due caratteristiche di C# qui, mi interessa spiegarmi di più di cosa sono?

new RouteValueDictionary() 
{ //<------------------------------[A: what C# feature is this?] -------|| 
    {"id",id}, //<------------------[B: what C# feature is this also?] || 
    {"saveChangesError",true}            || 
}); //<------------------------------------------------------------------|| 
+0

E 'la magia solo speciale in C# per chiamare automaticamente alcuni metodi ('add' in particolare) * dopo * l'oggetto è stato creato. –

+0

Per i rispondenti: can * inizializzazione proprietà * essere miscelato con * inizializzazione raccolta *? (Questo dovrebbe essere presente nello spiegare il costrutto "esterno", come avrebbe potuto essere: 'new Foo {Bar = Quz}'.) –

+0

@pst: No, nemmeno in VB.NET, abbastanza stranamente ... – Ryan

risposta

8

È una singola funzione - collection initializers. Come gli inizializzatori degli oggetti, può essere usato solo come parte di un'espressione di inizializzazione dell'oggetto, ma in pratica chiama Add con qualsiasi argomento presente - utilizzando le parentesi per specificare più argomenti o singoli argomenti alla volta senza le parentesi, ad es.

var list = new List<int> { 1, 2, 3 }; 

Vedere la sezione 7.6.10.3 della specifica C# 4 per ulteriori informazioni.

Si noti che il compilatore richiede due cose di un tipo per poter essere utilizzato per inizializzatori raccolta:

  • deve implementare IEnumerable, anche se il compilatore non genera chiamate a GetEnumerator
  • Si deve avere sovraccarichi adatti come Add metodo

Ad esempio:

using System; 
using System.Collections; 

public class Test : IEnumerable 
{ 
    static void Main() 
    { 
     var t = new Test 
     { 
      "hello", 
      { 5, 10 }, 
      { "whoops", 10, 20 } 
     }; 
    } 

    public void Add(string x) 
    { 
     Console.WriteLine("Add({0})", x); 
    } 

    public void Add(int x, int y) 
    { 
     Console.WriteLine("Add({0}, {1})", x, y); 
    } 

    public void Add(string a, int x, int y) 
    { 
     Console.WriteLine("Add({0}, {1}, {2})", a, x, y); 
    } 

    IEnumerator IEnumerable.GetEnumerator()   
    { 
     throw new NotSupportedException(); 
    } 
} 
+0

http://msdn.microsoft.com/en-us/ library/bb531208.aspx – pm100

+2

Abbiamo un link alla documentazione MSDN nella risposta, almeno. :) –

+0

@DanJ: Sì, ci sto arrivando :) –

7

Questa è sintassi di inizializzazione della raccolta. Questo:

RouteValueDictionary d = new RouteValueDictionary() 
{        //<-- A: what C# feature is this? 
    {"id",id},     //<-- B: what C# feature is this also?  
    {"saveChangesError",true} 
}); 

è sostanzialmente equivalente a questo:

RouteValueDictionary d = new RouteValueDictionary(); 
d.Add("id", id); 
d.Add("saveChangesError", true); 

Il compilatore riconosce il fatto che implementa IEnumerable e ha un metodo appropriato Add e utilizza tale.

See: http://msdn.microsoft.com/en-us/library/bb531208.aspx

+4

"sintassi di inizializzazione del dizionario" fa sembrare C# * come lingua * ha una conoscenza integrata dei dizionari. Non è così. Funzionerà con * qualsiasi * tipo che implementa 'IEnumerable' e ha i metodi' Add' appropriati. –

+1

@JonSkeet: come riconosce il fatto che si tratta di un 'KeyValuePair'? – Ryan

+3

@minitech: non è così. Riconosce il fatto che esiste un metodo 'Aggiungi (chiave, valore)'. Vedi la mia risposta per un esempio di questo. Si noti inoltre che, in realtà, la variabile viene assegnata * solo * dopo le chiamate "Aggiungi": è come se si avesse una variabile temporanea prima di quella. –

Problemi correlati