76

How do you break out of a foreach loop while within a switch block?

Normally, you use break but if you use a break within a switch block it will just get you out of a switch block and the foreach loop will continue execution:

foreach (var v in myCollection)
{
    switch (v.id)
    {
        case 1:
            if (true)
            {
                break;
            }
            break;
        case 2;
            break
    }
}

What I'm currently doing when I need to break out of the foreach while within the switch block is setting a bool value placed outside of the loop to true and checking the value of this bool every time the foreach is entered and before entering the switch block. Something like this:

bool exitLoop;
foreach (var v in myCollection)
{
    if (exitLoop) break;
    switch (v.id)
    {
        case 1:
            if (true)
            {
                exitLoop = true;
                break;
            }
            break;
        case 2;
            break
    }
}

This works but I keep thinking there must be a better way of doing this I am unaware of...

EDIT: Wonder why this was not implemented in .NET the really neat way it works in PHP as mentioned by @jon_darkstar?

$i = 0;
while (++$i) {
    switch ($i) {
    case 5:
        echo "At 5<br />\n";
        break 1;  /* Exit only the switch. */
    case 10:
        echo "At 10; quitting<br />\n";
        break 2;  /* Exit the switch and the while. */
    default:
        break;
    }
}
Dean Kuga
  • 11,878
  • 8
  • 54
  • 108
  • Not sure if a better way exists, but it would be similar to having to break out of an outer loop while being inside the inner loop. So far, I haven't found anyway to do that and hence using a flag value seems to be the only way. – Shamim Hafiz - MSFT Oct 28 '10 at 16:08
  • Possible duplicate of [Break out of a while loop that contains a switch statement](http://stackoverflow.com/questions/1987379/break-out-of-a-while-loop-that-contains-a-switch-statement) – ruffin Oct 29 '16 at 13:43
  • More than 15 years of experience tell me that sometimes goto is the best, fast and optimized option, keep the algorithm in one small place: keep it fast, efficient, atomic, without destroying it in a thousand pieces, reduce unnecessary calls. Examples, acoustic wave analysis, machine vision, real-time, etc. A flag will not make it slower, I see it as impossible, but many flags can be a reading problem. – Cheva Mar 30 '20 at 00:27

12 Answers12

83

Your solution is pretty much the most common option in this case. That being said, I'd put your exit check at the end:

bool exitLoop;
foreach (var v in myCollection)
{
    switch (v.id)
    {
        case 1:
            if (true)
            {
                exitLoop = true;
            }
            break;
        case 2;
            break
    }

    // This saves an iteration of the foreach...
    if (exitLoop) break;
}

The other main option is to refactor your code, and pull the switch statement and foreach loop out into a separate method. You could then just return from inside the switch statement.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
28

The boolean is one way. Another is using labels and goto. I know folks consider goto to be a cardinal sin, but used judiciously (VERY judiciously), it can be useful. In this case, place a label just past the end of the foreach loop. When you want to exit the loop, simply goto that label. For example:

foreach(var v in myCollection) {
    switch(v.Id) {
        case 1:
            if(true) {
                goto end_foreach;
            }
            break;
        case 2:
            break;
    }
}
end_foreach:
// ... code after the loop

EDIT: some people have mentioned taking the loop out into a separate method so that you can use return. I see the benefit of this as it doesn't require goto and it also simplifies the original function that contained the loop. However, if the loop is simple and is the primary purpose of the function that contains it, or if the loop makes use of out or ref variables, then it's probably best to just leave it in place and use the goto. In fact, because the goto and the label stand out, it probably makes the code clearer rather than clunkier. Putting it in a separate function could make simple code harder to read.

siride
  • 200,666
  • 4
  • 41
  • 62
  • 6
    Do not use goto. It makes code more complicated. Extract method is much better. – Andrew Bezzub Oct 28 '10 at 16:13
  • 10
    It'd better if you'd state *why* goto makes code more complicated, especially when the alternative is just as complicated and moves code away from its original context. – siride Oct 28 '10 at 16:15
  • Putting additional functions never makes code reading harder if your functions are short and name is clear. – Andrew Bezzub Oct 28 '10 at 16:16
  • And so he'd have to name the labels differently for each loop. Not a very good long term solution to use goto. – Neil Oct 28 '10 at 16:17
  • 13
    I think having a thousand little functions obscures the big picture. I know it's all the rage in the hardcore OO circles, but I find spelunking through a bunch of functions whose existence is motivated purely by reasons like "never use goto" to be considerable more difficult than dealing with a single slightly longer, but coherent function. – siride Oct 28 '10 at 16:18
  • @Neil only if he has many such loops in one function. If that were the case, then the argument for breaking the function down into multiple subfunctions would make a lot more sense. – siride Oct 28 '10 at 16:18
  • 7
    @Andrew Making a short function which is only ever called from exactly one place for the sole purpose of being able to return mid-function is hardly a better solution than `goto`. You have yet to justify your anti-goto sentiments beyond regurgitating popular opinion. – user229044 Oct 28 '10 at 16:29
  • 1
    @meagar. It is definitely better solution as long as function is atomic and you can understand what it does by just reading its name. Read http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882 – Andrew Bezzub Oct 28 '10 at 16:34
  • 1
    @Andrew Because if a book says so, it must be true. Some of us have formed our own opinions based on critical thought and experience. – user229044 Oct 28 '10 at 16:43
  • 3
    I'm pretty sure .NET architects would not include goto in the framework if they didn't feel there was a legitimate use for it and although this could be just such a case I'd still rather go with pulling the loop into a separate method as an alternative to using a flag... – Dean Kuga Oct 28 '10 at 16:44
  • 1
    @meagar Its not just the book, its Robert Martin. And of course I have my own opinion - goto should never be used. – Andrew Bezzub Oct 28 '10 at 17:44
  • 1
    @Andrew if the opinion isn't based on anything, then it's invalid. Give some reasons why goto should never be used (other than "I read a book that said it shouldn't be used"). – siride Oct 28 '10 at 18:17
  • 2
    @siride The book says nothing about goto. It says about writing clear code that is easy to maintain and understand. I just don't see any case when goto is easier to understand when you are reding code. – Andrew Bezzub Oct 28 '10 at 18:26
  • BTW, `goto` would be a "safe/sane" construct if it was an (optional - turn off for hard-core real-time coding) compile error to go to a label earlier in the method body. Likewise for jumping into middle of a code block (that calling site isn't already inside of). With these two restrictions, `goto` would only allow one to "break out multiple levels" (and possibly skip some code at the end of the outer level you are breaking. Basically, what people do now with flags. Given these two compile-time restrictions, `go-to` would be compatible with "structured coding" principles. – ToolmakerSteve Mar 31 '20 at 19:53
  • @ToolmakerSteve got me thinking... so many years out from the original question. That maybe something like "break [label];" where the label was a previously-labelled loop would be the acceptable construct. – Jason Jul 23 '21 at 22:46
  • @Jason - Indeed, some languages have a way to do this. **Java** has `labeled loops`. **PHP** has `break(N)`, where N is number of levels to break out of. **Visual Basic** can do in limited situations: If you have two DIFFERENT block or looping structures, such as a `Do` inside of a `Select`, you can get out of the outer one using the appropriate Exit; here `Exit Select`. – ToolmakerSteve Jul 24 '21 at 11:37
  • OTOH, the need is rare enough that setting and testing a boolean is an acceptable alternative. More importantly, I find that usually once code is complex enough for that to be needed, its best to factor out a method - to make the outer code more readable. Logically, the inner code is typically making some decision that might as well be given a name, and a value returned. Then its a "compiler optimization" problem as to when it would be efficient to inline that method, to avoid overhead. – ToolmakerSteve Jul 24 '21 at 11:46
  • @ToolmakerSteve The use case doesn't come up super frequently, but when it does it's frustrating.I generally tend toward factoring out a method, but there have been more than a handful of times where it was in that zone where it seemed like overkill. – Jason Aug 20 '21 at 20:54
17

You could extract your foreach cycle to the separate method and use return statement. Or you could do like this:

        foreach (object collectionElement in myCollection)
        {
            if (ProcessElementAndDetermineIfStop(collectionElement))
            {
                break;
            }
        }

        private bool ProcessElementAndDetermineIfStop(object collectionElement)
        {
            switch (v.id)
            {
                case 1:
                    return true; // break cycle.
                case 2;
                    return false; // do not break cycle.
            }
        }
Andrew Bezzub
  • 15,744
  • 7
  • 51
  • 73
13

Honestly? This is perhaps the only situation where it is completely valid and proper to use goto:

foreach (var v in myCollection) {
    switch (v.id) {
        case 1:
            if (true)
                // document why we're using goto
                goto finished;
            break;
        case 2;
            break
    }
}
finished: // document why I'm here
user229044
  • 232,980
  • 40
  • 330
  • 338
  • 2
    Why use goto? It is much better to extract method. Each time you use goto statement a kitten dies. – Andrew Bezzub Oct 28 '10 at 16:07
  • 5
    Why extract method when you can just goto? It's six in one, half dozen the other, really. If the loop is small enough to belong in a single function in the first place, it seems a bit odd to refactor it out solely to avoid a clean and clear goto. – siride Oct 28 '10 at 16:08
  • Because using goto causes pain. Your methods should as short as possible. And if they are you will never need goto statement. – Andrew Bezzub Oct 28 '10 at 16:11
  • 4
    @Andrew *miss-use* of goto causes pain, the same can be said for any and every language construct. – user229044 Oct 28 '10 at 16:13
  • 6
    What pain does it cause? return and break do effectively the same thing except there is no explicit label, potentially making the code less readable. The anti-goto canard needs to die. It's fine to rail against it from the days before procedural programming when people would truly write spaghetti code with nothing but gotos. Now that we mostly use higher-level constructs, the occasional goto is not a problem at all. The anti-goto hysteria is nothing more than cargo cult programming, AFAIC. – siride Oct 28 '10 at 16:14
  • 2
    I am 7 years late to this party but I whole heartedly agree with @siride. The 'goto killing kittens' myth must end. – Vanquished Wombat Jul 02 '17 at 21:53
8

It's not really different from your exitLoop flag, but it might be more readable if you extract a method...

foreach (var v in myCollection)
{
    if(!DoStuffAndContinue(v))
        break;
}


bool DoStuffAndContinue(MyType v)
{
    switch (v.id)
    {
        case 1:
            if (ShouldBreakOutOfLoop(v))
            {
                return false;
            }
            break;
        case 2;
            break;
    }
    return true;
}
dahlbyk
  • 75,175
  • 8
  • 100
  • 122
5

There's always the option of restructuring your code so that you can return from the switch statement.

Klaus Byskov Pedersen
  • 117,245
  • 29
  • 183
  • 222
2

Based on MSDN documentation on the break statement, it only allows to stop the top-most scope.

This case is one where you could use a goto statement to leave your foreach loop. If you don't want to use a goto statement, your solution seems to be the best one.

As a side note, you could improve your code by testing the exitLoop flag at the end of the iteration, saving the cost of one enumerator call.

Thibault Falise
  • 5,795
  • 2
  • 29
  • 32
  • Which I find quite unfortunate, especially since Java allows you to break out of multi-level loop/switch constructs with, e.g., "break 2" syntax. – siride Oct 28 '10 at 16:15
2

Some languages (i know PHP is one, not sure about others) allow you to specify how many control structures you'd like to break out of with

break n;
where 1 is implied if you just do break

break 2 would do what you describe, were it available in C#. I don't believe that's the case so your exit flag is probably the best solution.

jon_darkstar
  • 16,398
  • 7
  • 29
  • 37
1

Lame, I know, but that's all you can do about it.

You could always transform it into a while loop and add 'exitLoop' as a condition which must be met. Inside the switch, you can call continue to skip the rest of the current pass and since you would have set exitLoop to false, it'd exit much like break would do. Even though it's not exactly what you're asking, perhaps it's more elegant that way?

Neil
  • 5,762
  • 24
  • 36
0

Another way to do that is using goto, but extracting to a method would be preferable

int[] numbers = { 1, 2, 3, 4, 5 };
foreach (var number in numbers)
{
    switch (number)
    {
        case 1:
            break;
        case 2:
            goto breakLoop;
        default:
            break;
    }

}
breakLoop:
Console.Write("Out of loop");
Davi Fiamenghi
  • 1,237
  • 12
  • 28
  • I know goto has become taboo, but in all honesty this seems to be the cleanest solution. It clearly conveys the programmer's intent and does so with less ceremony. – Ayo I Oct 11 '20 at 14:20
-1

You can do it with Try/Catch.. But it might not be the best idea in the world, because it causes performance problems and does show nasty lines in the debug window.

try
{ 
foreach (var v in myCollection)
    {
        switch (v.id)
        {
            case 1:
                if (true)
                {
                    throw new SystemException("Break");
                }
                break;
            case 2;
                break;
        }
    }
} catch {}
One idea
  • 7
  • 1
  • 1
    Exceptions are not for flow control. And if they need to be, it should be for somewhat exceptional behavior, not something as normal as exiting a loop. – siride Jul 03 '17 at 01:21
  • Nobody should ever do this. I cannot overstate how wrong this is. If I could, I would happily pay the penalty to downvote this twenty times. It is like using your car's oil dipstick to stir your pancake batter. Technically, it works, but it is absolutely not a good idea. – Daniel May 28 '19 at 15:45
-2

Transform the switch() statement into a "if() else if() [...] else" series of statements so that the break exits from the foreach() loop.

Aliaksei Kliuchnikau
  • 13,589
  • 4
  • 59
  • 72
Senbei
  • 1
  • There are always several options to replace one method with another. But that does not answer the question. The Question is : How do you break out of a foreach loop while within a switch block? – moskito-x Oct 28 '12 at 14:57