break wcześniej kończy pętlę. continue pomija resztę bieżącej iteracji i przechodzi do następnej. Obie instrukcje dotyczą najbardziej wewnętrznej otaczającej pętli i działają tak samo w for, foreach, while i do while.
Wynik:
process order of 45
skip invalid total 0
process order of 120
skip invalid total -5
process order of 80
test order found, stopping
after the loop
continue przeskoczyło linię przetwarzania dla 0 i -5. break zatrzymało pętlę na 999, więc do 60 pętla nigdy nie doszła, a wykonanie wznowiło się od pierwszej instrukcji za pętlą.
break: zatrzymaj się, gdy odpowiedź jest znana
Typowe użycie break to wyszukiwanie: gdy już znajdziesz to, czego szukasz, nie ma powodu przeglądać reszty.
Wynik:
first invalid email at index 1
Iterator (i++) nie uruchamia się po break, więc i nadal zawierałoby indeks znalezionego elementu, gdyby było zadeklarowane poza pętlą. Przy prostych wyszukiwaniach to samo mówi wywołanie z biblioteki: Array.FindIndex(emails, e => !e.Contains("@")) zwraca indeks (lub -1), a emails.Any(e => !e.Contains("@")) z LINQ odpowiada, czy błędny adres w ogóle istnieje.
continue: przejdź do następnej iteracji
continue to klauzula strażnika dla pętli. Zamiast owijać właściwą pracę w if, odrzuć niechciane przypadki na samym początku:
Wynik:
pen costs 1.20
mug costs 8.00
To, dokąd continue przechodzi dalej, zależy od pętli. W pętli for uruchamia iterator, a potem sprawdza warunek. W pętli while skacze prosto do warunku, co prowadzi do klasycznego błędu:
int i = 0;
while (i < 10)
{
if (i % 2 == 0)
continue; // i++ below is skipped: i stays 0 forever
Console.WriteLine(i);
i++;
}
Aktualizuj licznik przed każdym continue albo użyj pętli for, w której aktualizacja jest w nagłówku i zawsze się wykonuje.
break wewnątrz switch wewnątrz pętli
W switch instrukcja break kończy sekcję przypadku. Gdy ten switch jest w pętli, break należy do switcha, a nie do pętli:
Wynik:
quit received
count = 2
Zwykłe break w przypadku "quit" zakończyłoby tylko switch, pętla działałaby dalej, a count wyniosłoby 3. goto skacze do etykiety za pętlą. Przeniesienie pętli do metody i napisanie return w tym przypadku też działa i nie wymaga etykiety.
Wychodzenie z pętli zagnieżdżonych
C# nie ma break z etykietą, jak break outer; w Javie. Gdy wyszukiwanie przechodzi przez dwie zagnieżdżone pętle, break w pętli wewnętrznej kończy tylko ją; pętla zewnętrzna przechodzi do następnego wiersza. Są trzy standardowe rozwiązania.
1. Flaga, którą sprawdza pętla zewnętrzna:
Wynik:
first free seat: row 1, seat 2
2. goto do etykiety za obiema pętlami. To jedyne miejsce, w którym wiele przewodników stylu C# akceptuje goto, bo wyraża dokładnie "wyjdź z obu pętli":
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
if (seats[row, col] == 0)
{
Console.WriteLine($"first free seat: row {row}, seat {col}");
goto done;
}
}
}
done:
Console.WriteLine("search finished");
3. Metoda z return, zwykle najczystsza, bo wyszukiwanie dostaje nazwę i może zwrócić wynik:
Wynik:
first free seat: row 1, seat 2
C# 7.0 wprowadził też funkcje lokalne, które pozwalają umieścić taką metodę pomocniczą wewnątrz metody wywołującej. Użyty tu wzorzec z parametrem out jest wyjaśniony na stronie o ref i out.
goto i etykiety
Etykieta to identyfikator zakończony dwukropkiem, a goto label; do niej skacze. Reguły są na tyle ścisłe, że zapobiegają najgorszym nadużyciom:
- Etykieta musi być w tej samej metodzie, w tym samym bloku co
gotoalbo w bloku go otaczającym. Z bloków można wyskakiwać na zewnątrz, ale nigdy do środka: skok spoza pętli do etykiety w jej ciele to błąd CS0159 (no such label within the scope of the goto statement). - Z bloku
finallynie można wyjść przezgoto,breakanicontinue. - Wewnątrz
switchinstrukcjegoto case 3;igoto default;przekazują sterowanie do innej sekcji. W ten sposób switch w C# wyraża przechodzenie między przypadkami, bo niejawne wpadnięcie do następnego przypadku to błąd kompilacji.
goto może też budować pętle (skok wstecz do etykiety), ale pętla while mówi to samo w formie, którą rozpozna każdy czytelnik. Zostaw goto do wychodzenia z pętli zagnieżdżonych i do sekcji switch.
return, throw i pętle
return opuszcza całą metodę, więc opuszcza też każdą pętlę w jej wnętrzu. throw robi to samo, zgłaszając wyjątek. Wewnątrz bloku try z finally wszystkie instrukcje break, continue, goto i return nadal wykonują blok finally, zanim sterowanie pójdzie dalej, dzięki czemu można bezpiecznie wyjść z pętli, która trzyma otwarty plik w bloku using.
| Instrukcja | Opuszcza | Kontynuuje w |
|---|---|---|
continue | bieżącą iterację | następnej iteracji (iterator, potem warunek) |
break | najbardziej wewnętrzną pętlę lub switch | instrukcji za nią |
goto label | dowolne otaczające bloki | etykiecie |
return | metodę | kodzie wywołującym |
throw | wszystko aż do pasującego catch | bloku catch |
Najczęściej zadawane pytania
Czym różni się break od continue w C#?
break natychmiast kończy najbardziej wewnętrzną pętlę (lub switch); wykonanie przechodzi za nią. continue kończy tylko bieżącą iterację i przeskakuje do następnej: w pętli for najpierw uruchamia się iterator, w while i do while najpierw sprawdzany jest warunek, a w foreach pobierany jest następny element.
Jak wyjść z pętli zagnieżdżonych w C#?
C# nie ma break z etykietą. Są trzy możliwości: ustawić flagę bool i sprawdzać ją w pętli zewnętrznej, przeskoczyć za obie pętle przez goto do etykiety albo przenieść pętle do metody i wyjść z niej przez return. Wersja z metodą jest zwykle najczystsza, bo daje wyszukiwaniu nazwę i wartość zwracaną.
Czy break wewnątrz switch wychodzi z pętli w C#?
Nie. Wewnątrz switch umieszczonego w pętli break kończy sekcję switch, a pętla działa dalej. Żeby wyjść z pętli z wnętrza przypadku, użyj return, flagi sprawdzanej za switchem albo goto do etykiety za pętlą. continue wewnątrz przypadku przechodzi do następnej iteracji pętli.
Czy goto jest dozwolone w C#?
Tak. goto label; skacze do label: w tej samej metodzie, ale nie może wskoczyć do bloku ani wyjść z finally. Wewnątrz switch instrukcje goto case value; i goto default; przeskakują między sekcjami. Poza wychodzeniem z pętli zagnieżdżonych i jawnym przechodzeniem między przypadkami switch goto rzadko jest najczytelniejszym wyborem.