2009-11-29 15 views
7

¿No está permitido tener un operador condicional en una expresión lambda en ForEach?¿Usando el operador condicional en la expresión lambda en ForEach() en una lista genérica?

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 += ""); 

Error de compilación -> "Sólo asignación, llamar, incremento, decremento, y nuevas expresiones de objetos se puede utilizar como una declaración"

Tratar de utilizar una normal si no funciona bien:

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

¿No es posible?

+2

Sheesh Estoy excepcionalmente impresionado con las respuestas, todo en unos minutos después de preguntar :) Creo que @SLaks responde al intento de mi pregunta, pero Aggregate() me deja boquiabierto. :) Gracias de nuevo a todos :) – Jamezor

+1

Tenías una expresión de cadena como un tipo de operador condicional, y necesitabas una declaración para tu método .ForEach(). Es por eso que el error de compilación estuvo allí. –

+1

@Roman - ¡Lo tengo ahora! Pienso en un? x: y como shorthand para if (a) {x} else {y} pero? devuelve el valor de x e y, que era una cadena en este caso ... – Jamezor

Respuesta

26

Está utilizando la forma más corta de expresiones lambda, que solo permite una sola expresión.
Necesita la forma larga, que permite varias instrucciones.

Por ejemplo: paréntesis

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

Proveedores:

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

+ = tiene una prioridad más alta que, que puede ser la razón de que está recibiendo el error?. Con paréntesis, el error puede desaparecer. Sin embargo, no está 100% seguro de esto ... las expresiones lambda pueden tener restricciones adicionales que impiden el uso de declaraciones de asignación.

ACTUALIZACIÓN:

En lugar de múltiples + = instrucciones, es mucho más limpio para poner el condicional en el lado derecho de la asignación, como esto:

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

ACTUALIZACIÓN 2:

Pero es incluso mejor simplemente usar Agregado() ya que está diseñado exactamente para este escenario. He aquí una muestra:

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

Pero creo @Matt Breckon's respuesta anterior (que acabo de ver como estaba a punto de publicar esto) es incluso mejor que mi ejemplo ya que trata de la eliminación de la terminal "". Mira su respuesta ... :-)

5

¿Qué estás tratando de lograr? ¿Estás tratando de formar una cadena de elementos separados por comas donde contienen un valor particular? En LINQ le lograrlo utilizando la siguiente:

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); 

El resultado de esto es el "Punto cuidado de I, artículo cuidado de I, artículo que me importa".

Nota: Agregado es una gran manera de asegurarse de que no hay arrastre ""

+0

Usar 'Aggregate' para sting concat es una idea muy clara en la que no he pensado. Podrías cambiarlo fácilmente para usar un 'StringBuilder' porque' StringBuilder' tiene una interfaz fluida. – SLaks

+0

ja, solo estaba agregando un ejemplo de código Aggregate() a mi respuesta inicial ... pero me gusta más tuyo. +1! –

4

El problema fue que la expresión

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

no es una declaración. Simplemente devuelve un valor que tiene el tipo string.

Hay un truco para hacer que funcione (sólo por diversión): Llamada

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

simplemente he añadido a .GetType() método para crear un comunicado de la expresión inicial, y compilado.

+0

Y para '.ForEach()' necesitabas una declaración :) –

Cuestiones relacionadas