Menu

C# break, continue und goto: Schleifen und verschachtelte Schleifen verlassen

Wie break, continue und goto in C# funktionieren: eine Schleife vorzeitig beenden, einen Durchlauf überspringen, break in einem switch, drei Wege aus verschachtelten Schleifen (ein Flag, goto oder eine Methode mit return) und der Bug mit continue in while, der zur Endlosschleife führt.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

break beendet eine Schleife vorzeitig. continue überspringt den Rest des aktuellen Durchlaufs und geht zum nächsten. Beide wirken auf die innerste umgebende Schleife und funktionieren in for, foreach, while und do while gleich.

Ausgabe:

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 ist für 0 und -5 über die Verarbeitungszeile gesprungen. break hat die Schleife bei 999 gestoppt, 60 wurde also nie besucht, und die Ausführung ging bei der ersten Anweisung nach der Schleife weiter.

break: aufhören, wenn die Antwort feststeht

Der typische Einsatz von break ist eine Suche: Sobald du gefunden hast, was du gesucht hast, gibt es keinen Grund, den Rest anzusehen.

Ausgabe:

first invalid email at index 1

Der Iterator (i++) läuft nach einem break nicht, i enthielte also noch den passenden Index, wenn es außerhalb der Schleife deklariert wäre. Für einfache Suchen sagt ein Bibliotheksaufruf dasselbe: Array.FindIndex(emails, e => !e.Contains("@")) gibt den Index zurück (oder -1), und emails.Any(e => !e.Contains("@")) aus LINQ beantwortet, ob es einen ungültigen gibt.

continue: zum nächsten Durchlauf springen

continue ist eine Guard Clause für Schleifen. Statt die eigentliche Arbeit in ein if zu packen, weise die unerwünschten Fälle am Anfang ab:

Ausgabe:

pen costs 1.20
mug costs 8.00

Wohin continue als Nächstes springt, hängt von der Schleife ab. In einer for-Schleife führt es den Iterator aus und prüft dann die Bedingung. In einer while-Schleife springt es direkt zur Bedingung, was zu einem klassischen Bug führt:

int i = 0;
while (i < 10)
{
    if (i % 2 == 0)
        continue;        // i++ below is skipped: i stays 0 forever
    Console.WriteLine(i);
    i++;
}

Aktualisiere den Zähler vor jedem continue, oder nimm eine for-Schleife, bei der die Aktualisierung im Kopf steht und immer läuft.

break in einem switch in einer Schleife

In einem switch beendet break den case-Abschnitt. Steht dieser switch in einer Schleife, gehört das break zum switch, nicht zur Schleife:

Ausgabe:

quit received
count = 2

Ein einfaches break im case "quit" hätte nur den switch beendet, die Schleife wäre weitergelaufen, und count wäre 3. Das goto springt zum Label nach der Schleife. Die Schleife in eine Methode zu verschieben und in diesem case return zu schreiben funktioniert ebenfalls und braucht kein Label.

Verschachtelte Schleifen verlassen

C# hat kein break mit Label wie break outer; in Java. Läuft eine Suche durch zwei verschachtelte Schleifen, beendet ein break in der inneren Schleife nur die innere; die äußere geht zur nächsten Zeile weiter. Es gibt drei Standardlösungen.

1. Ein Flag, das die äußere Schleife prüft:

Ausgabe:

first free seat: row 1, seat 2

2. goto zu einem Label hinter beiden Schleifen. Das ist die eine Stelle, an der viele C#-Styleguides goto akzeptieren, weil es genau „beide Schleifen verlassen“ ausdrückt:

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. Eine Methode mit return, meist die sauberste Lösung, weil die Suche einen Namen bekommt und ihr Ergebnis zurückgeben kann:

Ausgabe:

first free seat: row 1, seat 2

C# 7.0 hat außerdem lokale Funktionen eingeführt, mit denen du diese Hilfsmethode in die aufrufende Methode setzen kannst. Das hier verwendete Muster mit out-Parameter wird auf der Seite zu ref und out erklärt.

goto und Labels

Ein Label ist ein Bezeichner mit folgendem Doppelpunkt, und goto label; springt dorthin. Die Regeln sind streng genug, um den schlimmsten Missbrauch zu verhindern:

  • Das Label muss in derselben Methode stehen, im selben Block wie das goto oder in einem umgebenden. Du kannst aus Blöcken herausspringen, aber nie in einen hinein: Von außen zu einem Label in einem Schleifenrumpf zu springen ist Fehler CS0159 (no such label within the scope of the goto statement).
  • Einen finally-Block kannst du nicht mit goto, break oder continue verlassen.
  • In einem switch übergeben goto case 3; und goto default; die Kontrolle an einen anderen Abschnitt. So drückt ein C#-switch Durchfallen aus, denn implizit in den nächsten Fall zu fallen ist ein Kompilierfehler.

Mit goto lassen sich auch Schleifen bauen (Rücksprung zu einem Label), aber eine while-Schleife sagt dasselbe in einer Form, die jeder Leser erkennt. Behalte goto zum Verlassen verschachtelter Schleifen und für switch-Abschnitte.

return, throw und Schleifen

return verlässt die ganze Methode und damit auch jede Schleife darin. throw tut dasselbe, indem es eine Exception auslöst. In einem try-Block mit finally führen break, continue, goto und return den finally-Block trotzdem aus, bevor die Kontrolle weitergeht. Deshalb ist es sicher, aus einer Schleife auszusteigen, die in einem using-Block eine Datei offen hält.

AnweisungVerlässtWeiter bei
continueden aktuellen Durchlaufdem nächsten Durchlauf (Iterator, dann Bedingung)
breakdie innerste Schleife oder den innersten switchder Anweisung danach
goto labelalle umgebenden Blöckedem Label
returndie Methodedem Aufrufer
throwalles bis zu einem passenden catchdem catch-Block

Häufig gestellte Fragen

Was ist der Unterschied zwischen break und continue in C#?

break beendet die innerste Schleife (oder den innersten switch) sofort; die Ausführung geht danach weiter. continue beendet nur den aktuellen Durchlauf und springt zum nächsten: In einer for-Schleife läuft als Nächstes der Iterator, in while und do while wird als Nächstes die Bedingung geprüft, in foreach wird das nächste Element geholt.

Wie verlasse ich in C# verschachtelte Schleifen?

C# hat kein break mit Label. Die drei Optionen: ein bool-Flag setzen und in der äußeren Schleife prüfen, mit goto zu einem Label hinter beiden Schleifen springen oder die Schleifen in eine Methode verschieben und mit return verlassen. Die Methodenvariante ist meist die sauberste, weil die Suche dadurch auch einen Namen und einen Rückgabewert bekommt.

Verlässt break in einem switch die Schleife in C#?

Nein. In einem switch, der in einer Schleife steht, beendet break den switch-Abschnitt, und die Schleife läuft weiter. Um die Schleife aus einem case heraus zu verlassen, nimm return, ein Flag, das nach dem switch geprüft wird, oder goto zu einem Label nach der Schleife. continue in einem case geht dagegen zum nächsten Durchlauf der Schleife.

Ist goto in C# erlaubt?

Ja. goto label; springt zu label: in derselben Methode, kann aber nicht in einen Block hinein oder aus einem finally heraus springen. In einem switch springen goto case value; und goto default; zwischen Abschnitten. Außer zum Verlassen verschachtelter Schleifen und für explizites Durchfallen im switch ist goto selten die klarste Wahl.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S