2010-02-12 4 views
7

¿Alguien sabe si es posible salir de un ForEach genérico que utiliza lambda? p.ej.C# exit generic ForCada que utiliza lambda

someList.ForEach(sl => 
    { 
    if (sl.ToString() == "foo") 
     break; 

    // continue processing sl here 
    // some processing code 
    } 
); 

Este código en sí no se compilará. Sé que podría usar un foreach regular, pero para coherencia quiero usar lambda.

Muchas gracias.

+0

¿Hay alguna razón por la que DEBE hacerse de esta manera? Siempre he tenido cuidado con 'break;'. Fuera de una caja de interruptores, nunca he visto la necesidad de usarlos. – FrustratedWithFormsDesigner

+5

Uso 'break' y' continue' mucho. A veces no quieres que el cuerpo del loop se ejecute completamente, y 'break' /' continue' simplifica el código. –

+0

¿Hay alguna razón por la que prefiera una expresión Lambda para esto? –

Respuesta

17

Sure. Pero primero, tenga en cuenta que recomiendo esto; Digo que un operador de secuencia no debería tener un efecto secundario, y una declaración debería tener un efecto secundario. Si está haciendo algo en ese ForEach lambda, conviértalo en una declaración en el cuerpo de un bucle foreach en lugar de hacer que parezca un operador de secuencia.

Dicho esto, esto es lo que debes hacer. En primer lugar, se escribe a sí mismo un ParaCada que funciona en secuencias arbitrarias, no sólo enumera:

public static void ForEach<T>(this IEnumerable<T> sequence, Action<T> action) 
{ 
    foreach(var item in sequence) action(item); 
} 

Y ahora usted escribe su ruptura como esto:

someList 
    .TakeWhile(x=>x.ToString() != "foo") 
    .ForEach(sl=> 
    {/*your action here*/}); 
+0

Bart De Smet hizo varias cosas del tipo 'ForEach' comenzando con' if': http://community.bartdesmet.net/blogs/bart/archive/2009/07/11/bart-s-control-library-not- what-you-think-it-is-part-0.aspx. –

7

De MSDN

La siguiente las reglas se aplican a la variable alcance en expresiones lambda:

snip

Una expresión lambda no puede contener una declaración Goto, sentencia break o continuar declaración cuyo objetivo es fuera del cuerpo o en el cuerpo de un contenida función anónima.

No sé si eso ayuda dado el código que ha publicado. La cita relevante es del final del artículo de MSDN.

+0

La respuesta más relevante y completa hasta el momento. ¡Me gusta! –

1

Advertencia: ¡el código a continuación no se debe tomar en serio y se proporciona solo con fines de entretenimiento!

Puede 'simular' un continuar con un pronto retorno de esta manera:

Enumerable.Range(1, 20) 
      .ForEach(n => 
       { 
        if (n == 10) return; 
        Console.WriteLine("This is not 10: {0}", n); 
       }); 

Dicho esto, creo que los efectos secundarios dentro de lambda son una señal de que estás haciendo mal. Use un foreach apropiado en su lugar. O algo así como TakeWhile, como ya demostró amablemente Eric.

0

¿Qué tal esto?

 Enumerable.Range(1, 10) 
     .Where(x => x % 2 != 0) 
     .ToList() 
     .ForEach(x => Console.WriteLine(x));