5

I have a code snippet :

int n = 0;
for (int i = 0; i < 50;i++)
{
    n = checkStatus();
    switch (n)
    {
       case 1:
          break;
          break;//This is unreachable and so i cannot Terminate the For Loop within the SWITCH
    }
}

As described in a comment I cannot terminate the For Loop directly from the Switch, only if I declare a boolean and at the End of Switch test

if(LoopShouldTerminate)
    break;

PS : or maybe I'm very confused!

[POST] I got the message ,and the problem is Solved ,but i would like to asume that using Switch within a for loop isn't a god idea ,because i heard from lot of developer's i should break from loop in the moment when i get the desired result ,so using switch need's extra boolean or push the Int i value to 50 direclty , but what would happen if we're using while loop ?

Rosmarine Popcorn
  • 10,761
  • 11
  • 59
  • 89
  • I assume you're using a switch because there are many possible values of `n` that you've omitted from your code sample? – BoltClock Sep 08 '11 at 17:36
  • yes ,because it's a Native DataBase ,and im not sure for N Values ! – Rosmarine Popcorn Sep 08 '11 at 17:37
  • 1
    Use i = 50; or move the for() loop into a helper function so you can use return. – Hans Passant Sep 08 '11 at 17:40
  • 1
    This has been asked and answered before, http://stackoverflow.com/questions/1987379/break-out-of-a-loop-that-contains-a-switch-statement-c. Use a return statement instead of a break. – jac Sep 08 '11 at 17:40

8 Answers8

11

Solution 1: Move the loop and the switch to different methods:

for(int i = 0; i < 50; ++i)
{
    if (DoCheckStatus(i)) break;
}

...

bool DoCheckStatus(int i)
{
    switch(CheckStatus(i))
    {
        case 1 : return true;
        default: return false;
    }
}

Solution 2: Adapt the above to eliminate the loop with an eager extension method:

static void DoWhile<T>(this IEnumerable<T> sequence, Func<T, bool> predicate)
{
    foreach(T item in sequence) 
        if (!predicate(item)) return;
}

...

Enumerable.Range(0, 50).DoWhile(DoCheckStatus)

Solution 3: Adapt the above to eliminate the loop and the helper method:

Enumerable.Range(0, 50).DoWhile(i=> 
{ 
    switch(CheckStatus(i))
    {
        case 1 : return true;
        default: return false;
    }
});
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 1
    +1 for *eliminate control flow*. The LINQ version is so much easier to understand than the loop with nested switch ... not to mention more concise. – LBushkin Sep 08 '11 at 17:48
  • 2
    just remember that `TakeWhile` is lazy – Jimmy Sep 08 '11 at 17:49
  • Nitpicking: 'Adapt the above' _above_ the sample? Non native speaker, but shouldn't it be 'Adapt the below'? – Benjamin Podszun Sep 11 '11 at 10:52
  • @EricLippert wouldn't a different keyword for breaking from `switch-case` other than `break` have helped in cases like these? Why did you guys choose `break` for both loops and switch cases? – nawfal Oct 15 '13 at 10:20
  • 1
    The answer to your first question is "yes". The answer to your second question is too long to fit into a comment so I suggest that you take advantage of the fact that this is a question-and-answer site and ask a question. – Eric Lippert Oct 15 '13 at 14:40
6

You can use goto in order to break out of the loop within the switch.

        int n = 0;
        for (int i = 0; i < 50;i++)
        {
            n = checkStatus();
            switch (n)
            {
                case 1:
                    goto outofloop;

            }
        }

    :outofloop
        // more code

One of the few good uses of goto...

Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • 1
    For the love of all things sacred, please don't suggest this... there is always a way to NOT use `goto`. It is the bane of my existence. – Chad La Guardia Sep 08 '11 at 17:39
  • 4
    @Chad - care to explain why such a localized use of `goto` is _sooooo_ bad? – Oded Sep 08 '11 at 17:39
  • @Oded Yes you're right i can Declare a Finish Checkpoint under the For Loop and use goto Finish;. But i would assume so dont Use Switch within the for Loop if you have a Break Case ,and Breaks in loops when the result desired founded are very suggested from other's. – Rosmarine Popcorn Sep 08 '11 at 17:39
  • @Chad I know `goto` is verbotten in general, but this is a pretty sensible use of it. Yes, you can use a boolean test at the end (or even hijack the loop test and just set `i = 50;` before the case break) but a statement that says "I'm outta here" is pretty clear. And since C# doesn't support non-local gotos anyway, the code is never that hard to follow. – dlev Sep 08 '11 at 17:41
  • @Cody - they are called labeled statements. – Oded Sep 08 '11 at 17:41
  • 2
    @Oded its sloppy. I have yet to see a case where some simple re-factoring can't eliminate the tendency to use a `goto`. For example, extracting the loop to a method and using `return` would eliminate the need for this particular `goto`. – Chad La Guardia Sep 08 '11 at 17:41
  • 1
    @Chad: I'm also interested to hear an explanation as to why using goto in this circumstance is such a horrible solution. Simply being the bane of your existence is not a sufficient justification. – James Johnson Sep 08 '11 at 17:44
  • 1
    @Cody: Sloppy? It doesn't look to sloppy in this case. It actually looks like a perfectly reasonable solution. I was hoping for something *less* subjective. – James Johnson Sep 08 '11 at 17:45
  • 4
    @Chad - "GOTO considered harmful" is a relic of abuse of GOTO in specific languages. Like any other programming constructs, it has its place. – Oded Sep 08 '11 at 17:46
  • 1
    @James Its bad practice...There's just not a good justification for using it. In my opinion, it suggests a bad algorithm design. One of the reasons they are obsolete is because we have methods and functions (which work in much the same way, except give you added functionality). If you want to use `goto`, why not use a language like BASIC or just write in plain assembly and use some jumps everywhere... – Chad La Guardia Sep 08 '11 at 17:47
  • @Chad: In general, it's not something that you really *need* to use anymore, but in a case like this, where OP has clearly stated awareness of other alternatives (such as a simple flag), it is a reasonable suggestion. – James Johnson Sep 08 '11 at 17:50
  • 7
    @Chad: "break" is itself just a "goto", and it is not even a goto that does you the courtesy of labelling its target! I agree that there are probably more elegant ways to structure code than a switch nested in a loop, but in this particular case I have no problem whatsoever with stripping away the thin veneer that disguises that "break" is the same as "goto". – Eric Lippert Sep 08 '11 at 17:57
2

Can you place the loop inside of a method and just use return?

Example:

myLoopingMethod()
{
    int n = 0;
    for (int i = 0; i < 50;i++)
    {
        n = checkStatus();
        switch (n)
        {
            case 1:
                return;
        }
    }
}

Another option would be to use a traditional if/else instead of a switch/case. Then you can just use break and it will jump out of your for loop

Abe Miessler
  • 82,532
  • 99
  • 305
  • 486
2

Just change the value of i:

int n = 0;
        for (int i = 0; i < 50;i++)
        {
            n = checkStatus();
            switch (n)
            {
                case 1:
                    i += 50;
                    break;

            }
        }
rie819
  • 1,249
  • 12
  • 19
2

If there is no other code after the switch you can just check in the for loop itself whether to continue looping:

bool doContinue = true;
for (int i = 0; i < 50 && doContinue; i++)
{
    n = checkStatus();
    switch (n)
    {
        case 1:
            doContinue = false;

    }
}
BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
0

You could use a boolean.

                int n = 0;
            for (int i = 0; i < 50; i++)
            {
                bool shouldBreak = false;
                n = checkStatus();
                switch (n)
                {
                    case 1:
                        shouldBreak = true;
                        break;
                }

                if (shouldBreak)
                    break;
            }
mdm20
  • 4,475
  • 2
  • 22
  • 24
0

I don't know if there's other logic that needs to be performed after the loop is finished, but you could try using return instead. The other option is to set a boolean flag, and exit after the switch.

switch (n)
{
    case 1:
        return;
}
James Johnson
  • 45,496
  • 8
  • 73
  • 110
0

This smells of bad design; there are a couple of ways you could fix this:

If only one condition of your switch would break the outer loop, then simply check for that before entering the switch:

 if(n == 1)
    break;

 switch(n) { }

If multiple conditions can break the loop, refactor to a more linq style query:

Enumerable.Range(0, 50).FirstOrDefault(x => listOfBreakCodes.Contains(checkStatus());

That should call checkStatus up to 50 times until it encounters a 1 (or other break codes), and then doesnt continue evaluating elements.

Tejs
  • 40,736
  • 10
  • 68
  • 86