2010-10-14 17 views
22

Sto chiamando un metodo che restituisce una variabile List che contiene un oggetto di tipo Anonymous C#. Per esempio:Utilizzo di tipi anonimi C#

List<object> list = new List<object>(); 
foreach (Contact c in allContacts) { 
    list.Add(new { 
     ContactID = c.ContactID, 
     FullName = c.FullName 
    }); 
} 
return list; 

Come posso fare riferimento a questa proprietà del tipo nel codice Sto lavorando su come per esempio

foreach (object o in list) { 
    Console.WriteLine(o.ContactID); 
} 

so che il mio campione non è possibile, ho scritto solo modo per Diciamo che ho bisogno di identificare esattamente ogni proprietà del tipo anonimo.

Grazie!

Soluzione:

Non solo uno dei la risposta è corretta e/o suggerire una soluzione di lavoro. Ho finito per utilizzare l'opzione 3 della risposta di Greg. E ho imparato qualcosa di molto interessante per quanto riguarda lo dynamic in .NET 4.0!

+0

possibile duplicato del [Accesso C# Anonymous Type oggetti] (http://stackoverflow.com/questions/713521/accessing-c-sharp-anonymous-type-objects) – nawfal

risposta

32

Non è possibile restituire un elenco di tipo anonimo, dovrà essere un elenco di object. Così perderai le informazioni sul tipo.

Opzione 1
Non utilizzare un tipo anonimo. Se stai cercando di utilizzare un tipo anonimo in più di un metodo, quindi crea una classe reale.

Opzione 2
Non abbattuto il tipo anonimo a object. (Deve essere in un metodo)

var list = allContacts 
      .Select(c => new { c.ContactID, c.FullName }) 
      .ToList(); 

foreach (var o in list) { 
    Console.WriteLine(o.ContactID); 
} 

Opzione 3
Usa la parola chiave dinamica. (NET 4 richiesto)

foreach (dynamic o in list) { 
    Console.WriteLine(o.ContactID); 
} 

Opzione 4
Usa qualche riflessione sporco.

+1

Opzione 5. Restituisce una lista di tuple a due voci (es: 'Elenco >'). (ma optate per l'opzione 1.) –

+0

L'opzione 3 dice che mi manca il raccoglitore runtime Dinamic. Cos'è quello? Dovrei importare qualcosa? – Lorenzo

+3

+1 L'opzione 1 è davvero la migliore per riutilizzare il tipo in diversi metodi. –

3
foreach (var o in list) { 
    Console.WriteLine(o.ContactID); 
} 

questo funziona solo se la lista è IEnumerable<anonymous type>, come questo:

var list = allContacts.Select(c => new { 
     ContactID = c.ContactID, 
     FullName = c.FullName 
    }); 
} 

ma non si può tornare tipi anonimi, perché è necessario definire il tipo di ritorno (non è possibile tornare var) e i tipi anonimi non possono avere nomi. dovresti creare un tipo non anonimo se devi passarlo. I tipi effettivamente anonimi non dovrebbero essere usati troppo, tranne che all'interno di una query.

+1

Non è possibile restituire 'IEnumerable ' – Greg

+0

Il reso restituisce un avviso che non può eseguire una conversione implicita tra IEnumerable e List . Come devo cambiare la mia firma del metodo? – Lorenzo

+1

@Lorenzo come è stato menzionato, non è possibile restituire tipi anonimi, perché è necessario definire il tipo restituito e i tipi anonimi non possono avere nomi. dovresti creare un tipo non anonimo se devi passarlo. I tipi effettivamente anonimi non dovrebbero essere usati troppo, tranne che all'interno di una query. – Andrey

1

Non è possibile farlo con i tipi anonimi. Basta creare una classe/struct Contact e utilizzarla.

List<object> list = new List<object>(); 
foreach (Contact c in allContacts) { 
    list.Add(c); 
} 

Poi si può fare questo:

foreach (var o in list) { 
    Console.WriteLine(o.ContactID); 
} 

...o questo:

foreach (object o in list) { 
    Console.WriteLine(((Contact)o).ContactID); //Gives intellisense 
} 

Ovviamente si deve in questo caso basta fare creare una lista di contatto invece di un elenco di oggetti:

List<Contact> list = new List<Contact>(); 
foreach (Contact c in allContacts) { 
    list.Add(c); 
} 

EDIT: Missed parte essenziale della questione. Ora risolto.
MODIFICA: risposta modificata ancora una volta. Vedi sopra.

+0

o non è di tipo Contact, è un tipo anonimo. –

+0

questo è sbagliato. o non è istanza di 'Contact', ma istanza di tipo anonimo – Andrey

+0

Oh, mancava quella parte. Leggilo troppo velocemente. Gli altri sono corretti. Usa 'var'. –

0

sostituzione oggetto con var in per ogni costrutto può funzionare

+4

'Lista ' è ciò che suggerisci? – Andrey

2

Se si dispone di un metodo come questo:

List<object> GetContactInfo() { 
    List<object> list = new List<object>(); 
    foreach (Contact c in allContacts) { 
     list.Add(new { 
      ContactID = c.ContactID, 
      FullName = c.FullName 
     }); 
    } 
    return list; 
    } 

Non si dovrebbe davvero fare questo, ma c'è una tecnica very ugly and not future-proof che è possibile utilizzare :

static T CastByExample<T>(object target, T example) { 
    return (T)target; 
    } 

    // ..... 

    var example = new { ContactID = 0, FullName = "" }; 
    foreach (var o in GetContactInfo()) { 
    var c = CastByExample(o, example); 
    Console.WriteLine(c.ContactID); 
    } 

Essa si basa sul fatto (che può cambiare!) che il compilatore riutilizza i tipi anonimi per i tipi che hanno la stessa "forma" (proprietà nomi ei tipi) . Poiché il tuo "esempio" corrisponde alla "forma" del tipo nel metodo, lo stesso tipo viene riutilizzato.

Le variabili dinamiche in C# 4 sono il modo migliore per risolvere questo problema.

+8

Questo è grottesco, ma affascinante. – Greg

-1

userei

allContacts 
.Select(c => new { c.ContactID, c.FullName }) 
.ToList() 
.ForEach(c => { 
    ...do stuff; 
}); 

allora non avete bisogno di dichiarare a tutti. credo che meno dichiarazione, meno punto e virgola porta a meno bug

+1

Penso che tu abbia perso la vera domanda. Per favore leggilo di nuovo attentamente – Lorenzo

0

So che sono in ritardo per la festa ma sto cercando qualcos'altro e ho trovato questo article che risponde alla tua domanda.

È possibile eseguire il cast dell'elenco di oggetti nel tipo anonimo.

public static void Main() 
    { 
     foreach (object item in GetList()) 
     { 
      var x = Cast(item, new { ContactID = 0, FullName = "" }); 
      Console.WriteLine(x.ContactID + " " + x.FullName); 
     } 

    } 

    public static IEnumerable<object> GetList() 
    { 
     yield return new { ContactID = 4, FullName = "Jack Smith" }; 
     yield return new { ContactID = 5, FullName = "John Doe" }; 
    } 

    public static T Cast<T>(object obj, T type) 
    { 
     return (T)obj; 
    } 
0

Ritorna

public static void Main() 
{ 
    foreach (object item in GetList()) 
    { 
     var x = Cast(item, new { ContactID = 0, FullName = "" }); 
     Console.WriteLine(x.ContactID + " " + x.FullName); 
    } 

} 

public static IEnumerable<object> GetList() 
{ 
    yield return new { ContactID = 4, FullName = "Jack Smith" }; 
    yield return new { ContactID = 5, FullName = "John Doe" }; 
} 

public static T Cast<T>(object obj, T type) 
{ 
    return (T)obj; 
}