2010-12-14 11 views
13

Od foreach() Metoda pętli wszystkim członków listy Dlaczego nie użyć przerwa/kontynuować klauzuli natomiast mogę ich używać wewnątrz normalnej pętli foreachforeach(): Dlaczego nie można korzystać z przerwy/kontynuować wewnątrz

lstTemp.ForEach(i=> 
{ 
    if (i == 3) 
    break; 
    //do sth 
} 
); 

błąd:

"No enclosing loop out of which to break or continue"

+0

Dobrze napisany przedłużenie ForEach powinny umożliwić powrót na false, jeśli chcesz go złamać. Ale nie mogę powiedzieć tego na pewno, ponieważ nie wiem, skąd masz swoje foreach. Jeśli napisałeś to sam, może to być dobra opcja. – Tesserex

+0

Wygląda na to, że chcesz funkcji TakeWhile http://msdn.microsoft.com/en-us/library/bb534804%28v=VS.90%29.aspx – Juliet

+0

Znalazłem lepszą odpowiedź tutaj: http://stackoverflow.com/questions/3145563/list-foreach-break –

Odpowiedz

18

Ponieważ ForEach jest metodą, a nie regularną pętlą foreach. Metoda ForEach służy do wykonywania prostych zadań, jeśli chcesz przerwać lub kontynuować iterację ponad lstTemp za pomocą zwykłej pętli foreach.

Zazwyczaj ForEach jest realizowany tak:

public static ForEach<T>(this IEnumerable<T> input, Action<T> action) 
{ 
    foreach(var i in input) 
    action(i); 
} 

Ponieważ jest to normalne wywołanie metody, action nie nic o otaczającej foreach wiedzieć, a tym samym nie można złamać.

+0

Biorąc pod uwagę, że jest to wywołanie metody, czy mogę po prostu zwrócić zamiast przerwy? – Lance

+0

Nie, po prostu wrócisz z samej metody. W ten sposób nie będziesz mógł wyjść z zewnętrznego foreach. – Femaref

17

Przypuszczalnie dlatego używasz lambda i zawartość lambda są nieświadomi faktu, że jest on używany wewnątrz pętli.

2

Przerwij i kontynuuj to słowa kluczowe w języku C#, które wymagają obsługi kompilatora. ForEach, do kompilatora C#, jest po prostu metodą.

4

Sposób bym go wytłumaczyć to: ForEach jest metoda, a nie cecha język. Konstrukcja C# foreach jest cechą języka, w którym dozwolony jest inny język, który jest konstruowany w postaci break i continue.

Chciałbym również zwrócić uwagę (nie próbując osądzić, po prostu zrobić obserwację), że jest to dobry przykład, dlaczego niektórzy programiści sprzeciwiam się stosowaniu metody ForEach: to naprawdę nie zapisuje pisania w tym prostym przypadku , wymaga jeszcze jednego przekierowania, niż to konieczne, i mimo to nie ma całej funkcjonalności.

Moim zdaniem główny scenariusz, w którym metoda ForEach ma sens, jest rozszerzeniem na IEnumerable<T> - do umieszczenia na końcu łańcucha wywołań metod. Wydaje mi się (nieco) dziwne, że dodali ją do List<T>.

0

Ponieważ delegujesz akcję dla każdej pozycji na liście.

10

zamiast stosować przerwy, wykonać filtr pierwszy tak (może nie być dokładny filtr trzeba, ale ilustruje punkt)

lstTemp.Where(i => i!= 3).ForEach(i=> // do sth); 
+0

-1 Nie próbkowanie. Twój kod będzie działał dla każdego i! = 3. Przedstawiony kod będzie działać do i == 3. – Sergio

+0

Wydaje się, że jest to najlepszy sposób na kontynuowanie. Poza tym możemy po prostu napisać "return" dla "break". – Nigiri

0

Można napisać metodę rozszerzenia „ForEachWhile”, które odbywają a Function<T, bool> i zatrzymuje się, gdy wartość false.

5

iteracyjne tylko część elementów i naśladować przerwę doskonale, można użyć FirstOrDefault:

lstTemp.FirstOrDefault(i=> 
{ 
    if (i == 3) 
     return true; 

    //do stuff 

    return false; 
} 
); 

Na liście z 100000 pozycji, jeżeli w 10. pozycja jest 3 będzie iteracyjne tylko 10 razy, przy użyciu Rozwiązanie Where zadziała, ale najpierw przetestujemy całą listę.

+1

Metoda 'Where' nie wykonuje iteracji kolekcji, patrz: odroczone wykonanie. –

+0

@James może * iterować * nie jest właściwym słowem .. ale znaleźć wszystkie pasujące elementy, gdzieś jakoś wszystkie elementy muszą być sprawdzone, prawda? –

+1

Przeczytaj, jak działa słowo kluczowe "yield", ponieważ tak działają zapytania LINQ. Zbyt dużo czasu na wyjaśnienie, ale nie, nie wszystkie przedmioty muszą być sprawdzone; zostanie sprawdzonych tylko tyle elementów, ile żąda łańcuch połączeń. Dokładnie tak samo, jak twoje 'FirstOrDefault', które będzie iterować do momentu trafienia. –

-1

użyłem go

 list.ForEach((item) => 
     { 
      if(isBreak == false) do 
      { 
       if (isContinue) 
        break; 

       // TODO 
      } while (false); } 
     }); 
+0

to nie odpowiada dokładnie na pytanie. OP pyta, dlaczego nie może używać break/continue jak normalna pętla. – Rafael

+0

Spróbuj usunąć 'do-while' i użyj' break', LOL. – code4life

3

return będzie działać jako continue w ForEach.

przykład:

var list = new List<int>() {1, 2, 3, 4}; 
list.ForEach(i => 
    { 
     if (i == 3) 
      return; 
     Console.WriteLine(i); 
    } 
); 

wydruków 1, 2, 4

3 - pominięte.

1

Ponieważ ForEach jest metodą, a nie regularną pętlą foreach, należy iterować nad lstTemp z regularną pętlą foreach w przypadku break, ale w przypadku kontynuacji użyj return wewnątrz metody ForEach.

var lstTemp = new List<int>() {1, 2, 3, 4}; 
lstTemp.ForEach(i=> 
{ 
    if (i == 3) return; 
    //do sth 
    Console.WriteLine(i); 
}); 

Wyjście: 1, 2, 4

Powiązane problemy