2010-02-24 14 views
60

Esiste un modo per dichiarare un oggetto elenco di tipo anonimo. Voglio direDichiarazione dei tipi di elenco anonimi

List<var> someVariable = new List<var>(); 
someVariable.Add(
      new{Name="Krishna", 
       Phones = new[] {"555-555-5555", "666-666-6666"}} 
       ); 

Questo perché ho bisogno di creare una raccolta in fase di esecuzione. Grazie in anticipo

+2

Non capisco quale sia il punto di un elenco con tipi anonimi. –

+3

Ci sono alcuni casi d'uso per loro. Un esempio è quando è necessario combinare una query LINQ-to-SQL con una raccolta con memoria di riserva. – Polynomial

risposta

53

Coinvolge un po 'di hackery ma può essere fatto.

static List<T> CreateListFromSingle<T>(T value) { 
    var list = new List<T>(); 
    list.Add(value); 
    return list; 
} 

var list = CreateListFromSingle(
    new{Name="Krishna", 
       Phones = new[] {"555-555-5555", "666-666-6666"}} 
       ); 
+22

Ack. Questo è intelligente, e funziona, ma sarei così arrabbiato se qualcuno dei miei sviluppatori avesse mai fatto questo in un vero lavoro ... +1 per il bel trucco, però. –

+0

@Reed, d'accordo è doloroso guardare ma funziona – JaredPar

+0

senza offesa, ma spero che non usi questo codice ..: D –

13

Non è possibile creare una raccolta di un tipo anonimo come questo.

Se è necessario, è necessario utilizzare List<object> oppure creare una classe o una struttura personalizzata per il proprio tipo.


Edit:

sarò riformulare questo:

Anche se, tecnicamente, è possibile fare una lista di un tipo anonimo, consiglio vivamente mai fare questo. C'è sempre un approccio migliore, in quanto fare questo è solo rendere il codice praticamente impossibile da mantenere. Consiglio vivamente di creare un tipo personalizzato per conservare i valori anziché utilizzare tipi anonimi.

un tipo personalizzato avrà tutte le stesse funzionalità (dal momento che i tipi anonimi sono definiti, dal compilatore, al momento della compilazione), ma sarà molto più comprensibile dallo sviluppatore che ti segue ...


E solo per giocare, anche, ecco la mia voce per "codice non avevo mai in realtà voglio usare nel mondo reale":

var customer = new { Name = "Krishna", Phones = new[] { "555-555-5555", "666-666-6666" } }; 
var someVariable = new[]{1}.Select(i => customer).ToList(); 
+2

Concordato. Penso che una buona regola è che se sei preoccupato del tipo di un oggetto di tipo anonimo, allora stai facendo (o ti stai preparando) a fare qualcosa di sbagliato: – kervin

+1

+1 ci vuole mezzo secondo per creare un tipo personalizzato e risparmia ore di debug codice ingovernabile/confuso –

1

non credo che questo sia possibile. Forse in C# 4 usando la parola chiave dinamica?

+0

è possibile, ma non sarebbe una buona idea, questo è un buon esempio del perché alcune persone credono che la parola chiave 'dynamic' verrà abusata –

47

È possibile creare una lista come questa, ma sarà necessario ricorrere nuovamente a una serie di hackery e occorrerà utilizzare alcune situazioni di tipo "esempio". Per esempio:

// create the first list by using a specific "template" type. 
var list = new [] { new { Name="", Phones=new[] { "" } } }.ToList(); 

// clear the list. The first element was just an example. 
list.Clear(); 

// start adding "actual" values. 
list.Add(new { Name = "Krishna", Phones = new[] { "555-555-5555", "666-666-6666" } }); 
+12

Ok, questo è, ancora una volta, intelligente e terrificante allo stesso tempo ... +1 –

+2

Intelligente, non ho visto quel trucco in linea prima di – JaredPar

+1

Grazie, lo salverò per il futuro – Krishna

25

In generale è possibile utilizzare il (probabilmente puzzolente) espressi da altri esempio trucco hanno citato per creare istanze di qualsiasi tipo generico parametrizzati con un tipo anonimo per l'argomento tipo. Tuttavia, per List<T> c'è un modo un po 'meno grave di farlo:

var array = new[] { 
    new { 
    Name="Krishna", 
    Phones = new[] {"555-555-5555", "666-666-6666"} 
    } 
}; 
var list = array.ToList(); 

tuo schizzo di una sintassi proposto è simile ad una caratteristica non abbiamo implementiamo per C# 3 o 4, ma abbiamo preso in considerazione. Chiamiamo la funzione "tipi mumble", e sarebbe più o meno così:

List<?> myList = new List<?>() { 
    new { 
    Name="Krishna", 
    Phones = new[] {"555-555-5555", "666-666-6666"} 
    } 
}; 

Noi lo chiamiamo "tipi mumble" perché ovviamente che ci leggete "myList è un nuovo elenco di hrmmf". :-)

L'idea è che il compilatore guardi gli inizializzatori e faccia del suo meglio per capire quale potrebbe essere il tipo, proprio come "var" significa "guarda l'inizializzatore e calcola quale è il tipo di variabile ". Se usassimo "var" come "mumble" o "?" (che è simile a ciò che Java fa in una funzione correlata), o qualcos'altro è una domanda aperta.

In ogni caso, non terrei il fiato in attesa di questa funzione se fossi in te. Non ha fatto il taglio per diverse versioni linguistiche finora, ma rimarrà sulla lista delle possibilità per un po 'di tempo penso. Se, ipoteticamente parlando, dovessimo progettare versioni future della lingua. Che potremmo o non potremmo essere. Ricorda, le riflessioni di Eric sulle versioni future di C# sono solo a scopo di intrattenimento.

+1

+1 per il buon nome ("tipi mumble") e +1 per non averlo implementato. Immagino che il costo per farlo non sia economico, e il lavoro da fare per questo è abbastanza semplice, e più manutenibile ... – Daryl

8

ho speso un sacco di tempo cercando di trovare un modo per salvare me stesso un po 'di tempo utilizzando un elenco di tipi anonimi, poi capito che era probabilmente più veloce solo per usare una classe privata all'interno della classe corrente ...

private class Lookup { 
    public int Index; 
    public string DocType; 
    public string Text; 
} 
private void MyMethod() { 
    List<Lookup> all_lookups = new List<Lookup> { 
     new Lookup() {Index=4, DocType="SuperView", Text="SuperView XML File"}, 
     new Lookup() {Index=2, DocType="Word", Text="Microsoft Word Document"} 
    }; 
    // Use my all_lookups variable here... 

} 
8

Ecco un approccio che è un po 'più pulita rispetto a molti degli altri suggerimenti:

var list = Enumerable.Repeat(new { Name = "", Phones = new[] { "" } }, 0) 
       .ToList(); 

// ... 
list.Add(new { Name = "Krishna", 
       Phones = new[] { "555-555-5555", "666-666-6666" } }); 
+0

soluzione molto elegante - grazie gentile signore. –

61

ne dite di dinamica?

List<dynamic> dynamicList = new List<dynamic>(); 


dynamicList.Add(new { Name = "Krishna", Phones = new[] { "555-555-5555", "666-666-6666" } }); 
+0

Grazie a @JaiKannah, sicuramente dovrebbe essere la risposta per .NET 4.x. Ci porta molto più vicino alla flessibilità degli array PHP senza l'hacker. – sonjz

+0

Questa è una soluzione molto migliore rispetto agli altri ... – Octane

+5

'dynamic' = no intellisense. Grazie, ma no. 'Articolo1' è anche meglio della brutta tupla. – Sinatr