10

Possible Duplicate:
Breaking out of a nested loop

I got somthing like (to simplify)

foreach (...)
{
    foreach (...)
    {
        //Some code

        if (statement)
        {
            break;
        }
    }
}

The thing is that I want my statement to leave for the double-foreach loop ! I'm thinking about a sort of "break flag" as a boolean but is there any way to avoid that ?

Community
  • 1
  • 1
Guillaume Slashy
  • 3,554
  • 8
  • 43
  • 68

7 Answers7

13

You may use goto.

KV Prajapati
  • 93,659
  • 19
  • 148
  • 186
  • Without using a break flag, goto is pretty much the only option to jump out of multiple nested loops. – Tudor Nov 16 '11 at 11:05
  • @sll: Why? goto is a lot clearer than a flag in this case. KISS – jgauffin Nov 16 '11 at 11:05
  • 7
    Interesting - just mentioning `goto` causes immediate automatic downvotes ;) However weird it may sound, but exiting outer loops is done cleaner with `goto` than without it, so that's one scenario where using it is indeed justifyable. +1 – Yakimych Nov 16 '11 at 11:06
  • 2
    I don't like 'int' going to use for everything 'double' instead ;) – dowhilefor Nov 16 '11 at 11:09
  • 1
    I don't like `goto`, but this could be the only case in which it's to be used! Upvoted! – Marco Nov 16 '11 at 11:09
  • 1
    @jgauffin : I remembered rule `DO NOT USE goto for flow control` from university time studying Borland Pascal on the first course, I feel this rule makes sense and I treat goto as bad practice – sll Nov 16 '11 at 11:11
  • 1
    @sll - sorry that's not a justification it's an excuse for not having your own point of view. Did I mention I believe the world is flat because somebody told me it is? – Andras Zoltan Nov 16 '11 at 11:18
  • @AndrasZoltan Very frequently on this site answers are downvoted because of a perception of best practice. This is no different and is the reason I also downvoted. – Adam Houldsworth Nov 16 '11 at 11:22
  • 3
    @Andras Zoltan: Since we all born without any specific knowledges we are learn it from somewhere like development in university as a case, so this is original source where from knowledges may come into our minds and build/form our vision. So this is MY OWN point of view for this case. Even so I just suggesting not using it but understand another's point of view so I'm not downvoting such answers even I do not like it becuase it solves problem represented by the question – sll Nov 16 '11 at 11:28
  • It's called a holy war for a reason. OP: Don't use `goto`, and you'll make a lot of people happy. The ones who think you should use it won't notice that it is missing :) – Merlyn Morgan-Graham Nov 16 '11 at 11:41
  • @sll: Yes. We have all learnt that. But it's not for cases like this, but for languages like BASIC where it were frequently used (or misused). The term Spaghetti code was coined by the misuse of GOTO. imho the advice against GOTO is no longer valid for modern languages as we don't use GOTO that much anymore. – jgauffin Nov 16 '11 at 11:58
  • @AndrasZoltan: It's not really important if it's his personal view or not. It's a fact that most programmers have been brain washed to hate GOTO. And it ***WAS*** for a good reason. – jgauffin Nov 16 '11 at 12:00
  • @jgauffin - absolutely I do agree with that and do, I guess, shy away from goto because of that same latent hatred (after all I didn't think of that as an answer!); I think your most recent comment to @sll sums that up, though, it's not as relevant with today's languages given the wealth of flow-control statements we have. Explaining why loads of `goto`s is bad is easy - one or two here or there in the absence of something better, though, is much harder, so probably doesn't warrant that prejudice. – Andras Zoltan Nov 16 '11 at 12:48
11

You could avoid the nested loop entirely by using Linq and SelectMany.

Instead of:

foreach(var value in someValues)
{
    foreach(var subValue in value.SubValues)
    {
        // ...
        break;
    }
}

Your code would become:

foreach(var subValue in someValues.SelectMany(v => v.SubValues))
{
    // ...
    break;
}

If you need some logic to select whether or not you loop over SubValues, throw that logic in an additional Where clause.

Instead of

foreach(var value in someValues)
{
    if(value.IsMumsHairGreenToday)
    {
        foreach(var subValue in value.SubValues)
        {
            // ...
            break;
        }
    }
}

You can write:

var subValues = someValues
    .Where(v => v.IsMumsHairGreenToday)
    .SelectMany(v => v.SubValues)
    ;

foreach(var subValue in subValues)
{
    // ...
    break;
}
Merlyn Morgan-Graham
  • 58,163
  • 16
  • 128
  • 183
  • Im not confortable with lambda expressions so didnt think about doing this, sounds nice as I avoid the breakflag and use a GOTO ! – Guillaume Slashy Nov 16 '11 at 11:10
  • 4
    @GuillaumeCogranne: You will never get comfortable until you use them all the time. BTW: Please, don't ever use `goto`. I don't care what the crowd says. It is just sinful :) – Merlyn Morgan-Graham Nov 16 '11 at 11:12
9

You could try:

bool leave = false;
foreach (...)
{
    foreach (...)
    {
        //Some code

        if (statement)
        {
            leave = true;
            break;
        }
    }
    if (leave) break;
}

edit: moved the break flag

Tevo D
  • 3,351
  • 21
  • 28
Marco
  • 56,740
  • 14
  • 129
  • 152
6

Sure, you should check goto.

DanielB
  • 19,910
  • 2
  • 44
  • 50
2

As break only breaks out of the current loop you are going to have to test the break condition in the outer loop as well - unless you use a goto statement.

A variable would seem the best way of doing this.

ChrisF
  • 134,786
  • 31
  • 255
  • 325
2

Imo one of the few cases where a careful goto is fine.

dowhilefor
  • 10,971
  • 3
  • 28
  • 45
1

you could encapsulate that logic in a method and return at the break point:

private SomeType CheckIfConditionOfNestedItems(IEnumerable enumerable)
{
    foreach (var thing in enumerable )
    {
        foreach (...)
        {
            //Some code

            if (statement)
            {
                return result;
            }
        }
    }
}

obviously this might need you to change your code a little, but this also has the advantage that it probably makes the code where you have the double loop much more readable.

Sam Holder
  • 32,535
  • 13
  • 101
  • 181