2009-11-29 14 views
7

Non è consentito avere un operatore condizionale in un'espressione lambda in ForEach?Utilizzo dell'operatore condizionale nell'espressione lambda in ForEach() in un elenco generico?

List<string> items = new List<string>{"Item 1", "Item 2", "Item I Care About"}; 

string whatICareAbout = ""; 

// doesn't compile :(
items.ForEach(item => item.Contains("I Care About") ? 
whatICareAbout += item + "," : whatICareAbout += ""); 

errore di compilazione -> "Assegnazione Solo, chiamata, incremento, decremento, e nuove espressioni oggetto può essere usato come una dichiarazione"

Cercando di utilizzare un normale se non funziona neanche:

// :(
items.ForEach(item => if (item.Contains("I Care About")) {whatICareAbout += item + ", ";} 

Non è possibile?

+2

Sheesh Sono eccezionalmente impressionato dalle risposte, il tutto in pochi minuti dal chiedere :) Penso che @SLaks risponda all'intento della mia domanda, ma Aggregate() mi fa impazzire! :) Grazie ancora a tutti :) – Jamezor

+1

Hai avuto un'espressione di stringa come un tipo di operatore condizionale e avevi bisogno di una dichiarazione per il tuo metodo .ForEach(). Ecco perché l'errore di compilazione era lì. –

+1

@Roman - Ho capito ora! Penso a? x: y come short-hand per if (a) {x} else {y} ma? restituisce il valore di xey, che in questo caso era una stringa ... – Jamezor

risposta

26

Si sta utilizzando la forma più breve di espressioni lambda, che consentono solo una singola espressione.
È necessario il modulo lungo, che consente più istruzioni.

Ad esempio: parentesi

items.ForEach(item => { 
    if (item.Contains("I Care About")) 
     whatICareAbout += item + ", "; 
}); 
1

provare:

items.ForEach(item => item.Contains("I Care About") ? (whatICareAbout += item + ",") : (whatICareAbout += "")); 

+ = ha una precedenza superiore, che può essere il motivo che stai ricevendo l'errore?. Con parentesi, l'errore potrebbe andare via. Non sicuro al 100% di questo, anche se ... le espressioni lambda potrebbero avere ulteriori restrizioni che impediscono l'uso delle dichiarazioni di assegnazione.

UPDATE:

Invece di più + = istruzioni, è molto più pulito per mettere il condizionale sul lato destro del compito, in questo modo:

List<string> items = new List<string> { "one", "two", "three" }; 
string whatICareAbout = ""; 
items.ForEach(item => whatICareAbout += item.Contains("I Care About") ? (item + ",") : ""); 

UPDATE 2:

Ma è ancora meglio usare Aggregate() poiché è progettato proprio per questo scenario. Ecco un campione:

string whatICareAbout = items.Aggregate("", (total, item) => item.Contains("I Care About") ? (total + item + ",") : total); 

Ma penso @Matt Breckon's risposta di cui sopra (che ho appena visto come stavo per pubblicare questo) è ancora meglio che il mio esempio poiché si tratta di rimuovere il terminale "". Guarda la sua risposta ... :-)

5

Cosa stai cercando di ottenere? Stai cercando di formare una stringa di elementi separati da virgola dove contengono un valore particolare? In LINQ si dovrebbe raggiungere questo obiettivo utilizzando il seguente:

List<string> items = new List<string> { "Item 1", "Item 2", "Item I Care About", "Item I Care About", "Item I Care About" }; 
string whatICareAbout = items.Where(x => x.Contains("I Care About")) 
           .Aggregate((y, z) => y + ", " + z); 

L'output di questo è "Voce mi preoccupo, punto che mi interessa, punto che mi interessa".

Nota: Aggregate è un ottimo modo di garantire che vi sia alcuna finale ""

+0

L'uso di 'Aggregate' per pungere concat è un'idea molto carina che non ho pensato. Si potrebbe facilmente cambiarlo per usare un 'StringBuilder' perché' StringBuilder' ha un'interfaccia fluente. – SLaks

+0

hah, stavo solo aggiungendo un esempio di codice Aggregate() alla mia risposta iniziale ... ma mi piace il tuo migliore. +1! –

4

Il problema era che l'espressione

item.Contains("I Care About") ? whatICareAbout += item + "," : whatICareAbout += "" 

non è una dichiarazione. Restituisce solo un valore che ha tipo string.

C'è un trucco per farlo funzionare (solo per divertimento): chiamata

items.ForEach(item => (item.Contains("I Care About") ? 
    whatICareAbout += item + "," : whatICareAbout += "").GetType()); 

ho semplicemente aggiunto alla .GetType() metodo per creare una dichiarazione di espressione iniziale, ed è compilato.

+0

E per '.ForEach()' hai bisogno di una dichiarazione :) –

Problemi correlati