2013-05-16 10 views
14

Ho la seguente query:Assegnazione di valori all'interno di un LINQ Selezionare?

drivers.Select(d => { d.id = 0; d.updated = DateTime.Now; return d; }).ToList(); 

driver è una lista che viene fornito con diversi ID e valori aggiornati, quindi sto cambiando i valori nel Select, ma è il modo corretto per farlo. So già che non sto riassegnazione ai conducenti di piloti a causa ReSharper lamenta, quindi credo che sarebbe stato meglio se fosse stato:

drivers = drivers.Select(d => { d.id = 0; d.updated = DateTime.Now; return d; }).ToList(); 

, ma questo è ancora il modo in cui qualcuno dovrebbe assegnare nuovi valori per ciascun elemento l'elenco dei conducenti?

+0

possibile duplicato di [effetti collaterali Linq] (http: // stackoverflow.it/questions/5632222/linq-side-effects) – nawfal

risposta

33

Anche se questo sembra innocente, specialmente in combinazione con una chiamata ToList che esegue immediatamente il codice, non starei assolutamente a modificare qualcosa come parte di una query: il trucco è così insolito da far inciampare i lettori del programma , anche quelli esperti, soprattutto se non l'hanno mai visto prima.

Non c'è niente di sbagliato con foreach loop - il fatto che si può farlo con LINQ non significa che si dovrebbe essere facendo.

+0

Vorrei usare 'ForEach' per l'istruzione a riga singola, non per qualcosa che richiede parentesi graffe (più istruzioni). 'foreach' è davvero meglio qui. – nawfal

+0

Hai ragione, mi ha fatto inciampare :) Sono d'accordo anche con la tua seconda affermazione. – Xaisoft

+8

+1 LINQ non deve essere utilizzato per la mutazione dell'oggetto. – recursive

28

MAI FARE QUESTO. Una query deve essere una query ; dovrebbe essere non distruttivo fare domande su un'origine dati. Se si desidera causare un effetto collaterale, utilizzare un ciclo foreach; questo è quello che è per Usa lo strumento giusto per il lavoro.

+4

Grazie Eric. L'unico modo per conoscere il modo giusto è sapere che stai sbagliando in primo luogo :) – Xaisoft

7

Ok, risponderò io stesso.

Le query Xaisoft, Linq, che si tratti di espressione lambda o espressione di query, non devono essere utilizzate per modificare l'elenco. Quindi il tuo Select

drivers = drivers.Select(d => { d.id = 0; d.updated = DateTime.Now; return d; }).ToList(); 

è in cattivo stile. Confonde/illeggibile, non standard, e contro la filosofia Linq. Un altro stile poveri di raggiungere il risultato finale è:

drivers.Any(d => { d.id = 0; d.updated = DateTime.Now; return false; }); 

Ma questo non vuol dire ForEach su List<T> è inappropriato. Trova usi in casi come il tuo, ma non mischiare la mutazione con la query Linq, tutto qui. Preferisco scrivere qualcosa del tipo:

drivers.ForEach(d => d.updated = DateTime.Now); 

È elegante e comprensibile. Dal momento che non si occupa di Linq, non confonde troppo. Non mi piace la sintassi per le affermazioni multiple (come nel tuo caso) all'interno del lambda. È un po 'meno leggibile e più difficile da eseguire il debug quando le cose diventano complesse. Nel tuo caso preferisco un ciclo dritto foreach.

foreach (var d in drivers) 
{ 
    d.id = 0; 
    d.updated = DateTime.Now; 
} 

personalmente mi piace ForEach su IEnumerable<T>as a terminating call to Linq expression (cioè, se l'assegnazione non intende essere una query ma un'esecuzione).

+0

Grazie per la buona spiegazione. – Xaisoft

+0

@Xaisoft In realtà la cosa che odio di 'ForEach' su' Lista 'è il fatto che appaiono di default. Non penso che sia adatto come un costrutto a livello di struttura. Preferisco tali costrutti di livello superiore che arrivano a discrezione dell'utente, come estensione o così. Se gli oggetti su misura aiutano l'utente finale, provaci. C'è un sacco di geek che va là dentro e tocca alle persone selezionare se la sua produzione è adatta o meno. [Ecco un altro 'switch-case' implementato per' Tipo',] (http://stackoverflow.com/a/1426626/661933) è fantastico. Abbraccia o allontana. Non lamentarti .. – nawfal

+0

Chi ne lamenta e cos'è? – Xaisoft

Problemi correlati