2010-02-12 10 views
7

Qualcuno sa se è possibile uscire da un FOREach generico che usa lambda? per esempio.C# uscita generica ForEach che usa lambda

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

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

Questo codice non verrà compilato. So che potrei usare una foreach regolare ma per coerenza voglio usare lambda.

Molte grazie.

+0

C'è una ragione per cui DEVE essere fatto in questo modo? Sono sempre stato diffidente nei confronti di 'break;'. Al di fuori di un caso di commutazione, non ho mai visto la necessità di usarli. – FrustratedWithFormsDesigner

+5

Io uso 'break' e' continue' molto. A volte semplicemente non vuoi che il corpo del loop sia eseguito fino in fondo, e 'break' /' continue' semplifica il codice. –

+0

C'è qualche motivo per cui preferisci un'espressione Lambda per questo? –

risposta

17

Sicuro. Ma prima, nota che raccomando contro questo; Dico che un operatore di sequenza non dovrebbe avere un effetto collaterale, e una dichiarazione dovrebbe avere un effetto collaterale. Se stai facendo qualcosa in quel lambda ForEach, allora rendi una dichiarazione nel corpo di un ciclo foreach piuttosto che farlo apparire come un operatore di sequenza.

Detto questo, ecco quello che fai. In primo luogo, si scrive voi stessi un ForEach che funziona su sequenze arbitrarie, non elenca solo:

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

E ora si scrive la pausa in questo modo:

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

Bart De Smet ha fatto diverse cose di tipo 'ForEach' che iniziano con' if': http://community.bartdesmet.net/blogs/bart/archive/2009/07/11/bart-s-control-library-not- what-you-think-it-is-parte-0.aspx. –

7

Da MSDN

Il seguente le regole si applicano allo scope variabile nelle espressioni lambda:

snip

un'espressione lambda non può contenere una dichiarazione goto, break dichiarazione, o istruzione continue la cui destinazione è fuori del corpo o nel corpo di un contenuta funzione anonima.

Non so se questo aiuta dato il codice che hai postato. La citazione pertinente è dalla fine dell'articolo MSDN.

+0

La risposta più pertinente e completa ancora. Mi piace! –

1

Attenzione: il codice seguente non deve essere preso sul serio e viene fornito solo a scopo di intrattenimento!

Si puo 'simulare' continua con un ritorno anticipato in questo modo:

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

Detto questo, penso che gli effetti collaterali all'interno lambda di sono un segno che si sta facendo male. Utilizzare invece un foreach appropriato. O qualcosa come TakeWhile, come Eric ha gentilmente dimostrato.

0

Che ne dici di questo?

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