break ends a loop early. continue skips the rest of the current iteration and moves to the next one. Both apply to the innermost enclosing loop, and they work the same way in for, foreach, while and do while.
Output:
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 jumped over the processing line for 0 and -5. break stopped the loop at 999, so 60 was never visited, and execution resumed at the first statement after the loop.
break: Stop When the Answer Is Known
The typical use of break is a search: once you have found what you were looking for, there is no reason to look at the rest.
Output:
first invalid email at index 1
The iterator (i++) does not run after a break, so i would still hold the matching index if it were declared outside the loop. For simple searches, a library call says the same thing: Array.FindIndex(emails, e => !e.Contains("@")) returns the index (or -1), and LINQ's emails.Any(e => !e.Contains("@")) answers whether a bad one exists.
continue: Skip to the Next Iteration
continue is a guard clause for loops. Instead of wrapping the real work in an if, reject the cases you do not want at the top:
Output:
pen costs 1.20
mug costs 8.00
Where continue goes next depends on the loop. In a for loop it runs the iterator and then tests the condition. In a while loop it jumps straight to the condition, which leads to a classic bug:
int i = 0;
while (i < 10)
{
if (i % 2 == 0)
continue; // i++ below is skipped: i stays 0 forever
Console.WriteLine(i);
i++;
}
Update the counter before any continue, or use a for loop, where the update lives in the header and always runs.
break Inside a switch Inside a Loop
In a switch, break ends the case section. When that switch sits in a loop, the break belongs to the switch, not the loop:
Output:
quit received
count = 2
A plain break in the "quit" case would have ended only the switch, the loop would have continued, and count would be 3. The goto jumps to the label after the loop. Moving the loop into a method and writing return in that case works as well and needs no label.
Breaking Out of Nested Loops
C# has no labeled break like Java's break outer;. When a search runs through two nested loops, a break in the inner loop only ends the inner one; the outer loop moves to its next row. There are three standard fixes.
1. A flag that the outer loop checks:
Output:
first free seat: row 1, seat 2
2. goto to a label after both loops. It is the one place where many C# style guides accept goto, because it expresses exactly "leave both loops":
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. A method with return, usually the cleanest, because the search gets a name and can return its result:
Output:
first free seat: row 1, seat 2
C# 7.0 also introduced local functions, which let you put that helper method inside the calling method. The out-parameter pattern used here is explained on the ref and out page.
goto and Labels
A label is an identifier followed by a colon, and goto label; jumps to it. The rules are strict enough to prevent the worst misuse:
- The label must be in the same method, in the same block as the
gotoor an enclosing one. You can jump out of blocks but never into one: jumping to a label inside a loop body from outside is error CS0159 (no such label within the scope of the goto statement). - You cannot leave a
finallyblock withgoto,breakorcontinue. - Inside a
switch,goto case 3;andgoto default;transfer control to another section. This is how a C# switch expresses fall-through, since falling into the next case implicitly is a compile error.
goto can also build loops (jumping backwards to a label), but a while loop states the same thing in a form every reader recognizes. Keep goto for leaving nested loops and for switch sections.
return, throw and Loops
return leaves the whole method, so it also leaves every loop in it. throw does the same by raising an exception. Inside a try block with a finally, all of break, continue, goto and return still run the finally block before control moves on, which is what makes it safe to break out of a loop that holds a file open in a using block.
| Statement | Leaves | Continues at |
|---|---|---|
continue | the current iteration | the next iteration (iterator, then condition) |
break | the innermost loop or switch | the statement after it |
goto label | any enclosing blocks | the label |
return | the method | the caller |
throw | everything up to a matching catch | the catch block |
Frequently Asked Questions
What is the difference between break and continue in C#?
break ends the innermost loop (or switch) immediately; execution continues after it. continue ends only the current iteration and jumps to the next one: in a for loop the iterator runs next, in while and do while the condition is tested next, in foreach the next element is fetched.
How do I break out of nested loops in C#?
C# has no labeled break. The three options are: set a bool flag and test it in the outer loop, jump past both loops with goto to a label, or move the loops into a method and return from it. The method version is usually the cleanest, because it also gives the search a name and a return value.
Does break inside a switch exit the loop in C#?
No. Inside a switch that sits in a loop, break ends the switch section and the loop carries on. To leave the loop from inside a case, use return, a flag checked after the switch, or goto a label after the loop. continue inside a case does go to the loop's next iteration.
Is goto allowed in C#?
Yes. goto label; jumps to label: in the same method, but it cannot jump into a block or out of a finally. Inside a switch, goto case value; and goto default; jump between sections. Outside of leaving nested loops and explicit switch fall-through, goto is rarely the clearest choice.