2013-03-12 4 views
5

È possibile creare un metodo di estensione per restituire una singola proprietà o un campo in un elenco di oggetti?Come raccogliere una singola proprietà in un elenco di oggetti?

Attualmente ho molte funzioni come la seguente.

public static List<int> GetSpeeds(this List<ObjectMotion> motions) { 
    List<int> speeds = new List<int>(); 
    foreach (ObjectMotion motion in motions) { 
     speeds.Add(motion.Speed); 
    } 
    return speeds; 
} 

Questa è "hard coded" e serve solo una singola proprietà in un unico tipo di oggetto. È noioso e sono sicuro che c'è un modo per usare LINQ/Reflection per creare un metodo di estensione che possa farlo in modo generico e riutilizzabile. Qualcosa di simile a questo:

public static List<TProp> GetProperties<T, TProp>(this List<T> objects, Property prop){ 
    List<TProp> props = new List<TProp>(); 
    foreach (ObjectMotion obj in objects) { 
     props.Add(obj.prop??); 
    } 
    return props; 
} 

A parte il metodo più semplice utilizzando LINQ, sto anche cercando il metodo più veloce. È possibile utilizzare la generazione di codice (e gli alberi di espressione Lambda) per creare un tale metodo in fase di runtime? Sono sicuro che sarebbe più veloce dell'utilizzo di Reflection.

+0

La funzione potrebbe essere scritta come "motions.Select (motion => motion.Speed)". Questo non è esattamente generico, ma per cominciare è molto più breve di scrivere e chiamare un metodo ogni volta. – nvoigt

+0

Solo chiamare il mio metodo potrebbe essere più veloce. (LINQ è di solito più lento del codice non generico) –

risposta

7

si potrebbe fare:

public static List<TProp> GetProperties<T, TProp>(this IEnumerable<T> seq, Func<T, TProp> selector) 
{ 
    return seq.Select(selector).ToList(); 
} 

e usarlo come:

List<int> speeds = motions.GetProperties(m => m.Speed); 

è discutibile se questo metodo è meglio che solo utilizzando direttamente Select e ToList.

5

Si tratta, nessuna riflessione necessaria:

List<int> values = motions.Select(m=>m.Speed).ToList(); 
+0

Come posso creare un metodo di estensione per fare ciò? Non voglio scrivere questo frammento ogni volta. E come posso usare la generazione del codice per creare il metodo più veloce? –

+0

elenco statico pubblico GetValues ​​ (questo target , selettore Func ) {return target.Select (selectoror);} –

+1

ma non è necessario eseguire alcuna funzione, selezionare * è * una funzione già –

1

Un ciclo for sarebbe il più veloce, penso, seguito da vicino da linq (overhead minimo se non si utilizzano le chiusure). Non riesco a immaginare nessun altro meccanismo sarebbe meglio di così.

È possibile sostituire lo List<int> con un int[] o inizializzare l'elenco con una determinata capacità. Probabilmente farebbe di più per velocizzare il codice di qualsiasi altra cosa (anche se non è ancora molto).