2010-02-12 8 views
7

Weiß jemand, ob es möglich ist, ein generisches ForEach zu beenden, das Lambda verwendet? z.B.C# Exit Generika ForEach, die Lambda verwenden

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

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

Dieser Code selbst wird nicht kompiliert. Ich weiß, dass ich eine normale foreach verwenden könnte, aber aus Gründen der Konsistenz möchte ich Lambda verwenden.

Vielen Dank.

+0

Gibt es einen Grund, dass es so gemacht werden muss? Ich war immer auf der Hut vor 'break;'. Außerhalb eines Schaltkastens habe ich nie gesehen, dass ich sie benutzen muss. – FrustratedWithFormsDesigner

+5

Ich benutze 'break' und' continue' viel. Manchmal möchte man nicht, dass der Schleifenkörper den ganzen Weg durchläuft, und "break"/"continue" vereinfacht den Code. –

+0

Gibt es einen Grund, warum Sie einen Lambda-Ausdruck dafür bevorzugen? –

Antwort

17

Sicher. Aber zuerst, beachten Sie, dass ich dagegen empfehle; Ich sage, dass ein Sequenzoperator keine Nebenwirkung haben sollte, und eine Aussage sollte einen Nebeneffekt haben. Wenn Sie etwas in diesem ForEach-Lambda tun, machen Sie es im Körper einer foreach-Schleife zu einer Aussage, anstatt es wie einen Sequenzoperator aussehen zu lassen.

Das sagte, hier ist was du tust. Zuerst Sie sich eine ForEach schreiben, die auf beliebige Sequenzen arbeitet, nicht nur auflistet:

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

Und jetzt schreiben Sie Ihre Pause wie folgt aus:

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

Bart De Smet hat mehrere "ForEach" -Typen gemacht, die mit 'if' beginnen: http://community.bartdesmet.net/blogs/bart/archive/2009/07/11/bart-s-control-library-not- was-du-denk-es-ist-Teil-0.aspx. –

7

Von MSDN

Die folgende Regeln gelten für die Variable Bereich in Lambda-Ausdrücke:

snip

kann eine Lambda-Ausdruck enthält eine Aussage nicht goto-Anweisung, brechen oder Anweisung weiterhin deren Ziel außerhalb des Körpers oder in dem Körper eines anonyme Funktion enthalten.

Ich weiß nicht, ob das hilft angesichts der Code, den Sie gebucht haben. Das entsprechende Zitat stammt vom Ende des MSDN-Artikels.

+0

Die relevanteste und vollständigste Antwort noch. Ich mag das! –

1

Achtung: Der untenstehende Code ist nicht ernst zu nehmen und dient nur Unterhaltungszwecken!

Sie können ‚simulieren‘ ein, wie dies mit einer frühen Rückkehr fortsetzen:

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

Das heißt, ich glaube, dass die Nebenwirkungen innerhalb von Lambda ist ein Zeichen dafür, dass Sie tun es falsch. Benutze stattdessen eine richtige foreach. Oder etwas wie TakeWhile, wie Eric es freundlicherweise bereits gezeigt hat.

0

Wie wäre es damit?

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