2012-10-20 9 views
33

Ho una lista (dove T è una classe personalizzata e la classe ha alcune proprietà). Vorrei sapere come cambiare uno o più valori inide di esso utilizzando Lambda Expressions, quindi il risultato sarà lo stesso del ciclo foreach muggito:Modifica un valore all'interno dell'elenco <T>

NOTA: la lista contiene più elementi all'interno (più righe)

 foreach (MyClass mc in list) 
     { 
      if (mc.Name == "height") 
       mc.Value = 30; 
     } 

E questa la query LINQ (usando le espressioni lambda), ma la sua non è la stessa come il ciclo foreach superiore, restituisce solo 1 articolo (una riga) dalla lista!

Quello che voglio è, che restituisce tutti gli elementi (tutti i file) e chnages solo quella appropriata (gli elementi specificati nel metodo estensione WHERE (s)

list = list.Where(w => w.Name == "height").Select(s => { s.Value = 30; return s; }).ToList(); 

. NOTA: questi 2 esempio non sono la stessa cosa! Ripeto, il linq restituisce solo 1 elemento (una riga), e questo è qualcosa che non voglio, ho bisogno anche di tutti gli elementi della lista (come il ciclo foreach, solo le modifiche, ma non lo fa rimuovere qualsiasi articolo)

+5

* Perché * si desidera utilizzare le espressioni lambda? Il codice 'foreach' funziona bene ed è semplice. LINQ serve * per interrogare * i dati, non per mutarli. –

+1

Dove, per definizione, restituisce solo i record corrispondenti. Fondamentalmente: non è quello che vuoi - basta usare foreach –

+0

Ciao Jon, so che il ciclo foreach se la pastella e più veloce, ma mi piacerebbe imparare, questo è tutto. Per alcuni "piccoli" codici andrà bene. Ma il punto è soprattutto la lettura. –

risposta

64

È possibile utilizzare ForEach, ma è necessario convertire lo IEnumerable<T> in un List<T>.

list.Where(w => w.Name == "height").ToList().ForEach(s => s.Value = 30); 
+0

Crea una nuova lista. Chopps of items where Name! = "Height" – Tilak

+0

Crea un nuovo elenco - E restituisce solo gli elementi in base alla clausola WHERE. Non un esempio che voglio –

+0

@MitjaBonca mio male, ho frainteso la tua domanda. Vedi la mia modifica sopra. – McGarnagle

2

Si potrebbe utilizzare una proiezione con un lambda dichiarazione, ma il foreach circuito originale è più leggibile e sta modificando la lista in luogo piuttosto che la creazione di un nuovo elenco.

var result = list.Select(i => 
    { 
     if (i.Name == "height") i.Value = 30; 
     return i; 
    }).ToList(); 

Metodo di estensione

public static void SetHeights(this IEnumerable<MyClass> source, int value) 
{ 
    foreach (var item in source) 
    { 
     if (item.Name == "height") 
     { 
      item.Value = value; 
     } 

     yield return item; 
    } 
} 

var result = list.SetHeights(30).ToList(); 
+0

È possibile evitare se il blocco? Per definire forse selezionare il metodo di estensione? –

+0

Sì, è possibile definire un metodo di estensione personalizzato, ma il foreach originale è meno oscuro e più facile da mantenere e non creerà un nuovo elenco che potrebbe risultare costoso. – devdigital

+0

So come fare un metodo di exusione del cusom, mi chiedevo solo se è possibile farlo in un modo "breve", riguardo al codice ?! Come l'esempio mostrato da @Robin, solo che il suo codice non funziona! –

-2

Si può fare qualcosa di simile:

var newList = list.Where(w => w.Name == "height") 
       .Select(s => new {s.Name, s.Value= 30 }).ToList(); 

ma preferirei scegliere di utilizzare foreach perché LINQ è per l'interrogazione, mentre si desidera modifica i dati.

+0

Ho superato anche questo, ma ho ottenuto un'eccezione: "Dichiaratore di membro di tipo anonimo non valido. I membri di tipo anonimo devono essere dichiarati con un'assegnazione membro, un nome semplice o un accesso membro.". Questo è per "s.Value = 30". –

+0

Non è un esempio che voglio, anche se non funziona troppo. –

8

probabilmente sarei andare con questo (So che la sua LINQ non pura), tenere un riferimento all'elenco originale se si desidera mantenere tutti gli elementi, e si dovrebbe trovare i valori aggiornati sono in là:

foreach (var mc in list.Where(x => x.Name == "height")) 
    mc.Value = 30; 
1

Che ne dici di list.Find(x => x.Name == "height").Value = 20; Questo funziona correttamente. So che è un vecchio post, ma mi sono chiesto perché nessuno ha suggerito questo? C'è un inconveniente in questo codice?

+0

se 'list.Find (x => x.Name ==" height ")' non restituisce nulla, ottenendo errore '[NullReferenceException: riferimento oggetto non impostato su un'istanza di un oggetto.]' –

+0

È sempre possibile fare un null controllare prima di modificare effettivamente il valore. –

Problemi correlati