Exiting Nested Loops

Cags

Contributor
Joined
Feb 19, 2004
Messages
695
Location
Melton Mowbray, England
What is the best way of getting out of a nested loop (using c#), I know that you can exit a single Loop with the break; command,

C#:
for(int i = 0; i < iCount; i++)
{
    if(RequirementMet) // situation on which I want to exit
        break;
}

but I'm unsure of the best way of exiting a nested loop, this is the way I'm currently doing it.

C#:
for(int i = 0; i < iWidth; i++)
   for(int(j = 0; j < iHeight; j++)
      if(ReqruirementMet)
         goto BreakLoop;

BreakLoop:

Is this the best approach, I remember reading somewhere that the goto command isn't particularly good coding practice, but I don't know of any other obvious way to exit.
 
Goto is probably your best option in this case. Be careful of blanket statements like 'goto is bad' without qualifying why or when - if goto was that bad a construct it wouldn't be needed in C#.
With decent OO design goto will normally result in harder to read / maintain code, if however it's use can be justified i.e. it produces the cleanest code to suit the task at hand then use it.
 
A while loop might work better:
C#:
while(!requirementMet && i<Max)
{
      while(j<10 && !requirmentMet)
      {
           if(j*i=4)
           {
               requirementMet = true;
           }
           else 
           {
              j++;
           }
      }
      if(!requirementMet && i==84)
      {
           requirementMet = true;
      }
      else
      {
           i++;
      }
}
I avoid breaks when at all possible. Increase readability and debugging in my opinion.
 
My opinion is that goto is 100% not necesary at any time (at least not in .Net). If you are in a situation that you think requires Goto, then there is probably another way that is a better representation of the problem at hand. I think that bri189a is on to something. Think about your loop invariant a little more. You don't really want to loop through everything a la for loop style, you really only want to loop until the requirement is met (while !requirementMet). I prefer seeing the actual condition for looping up front instead of in the center of a few nested loops. That's readability.

I'd wager that there is another way to write this loop that doesn't use a goto statement and still gets the job done while being readable and maintainable.
 
I respect your opinions, but I personally find the goto statement easier to read. So long as it is clearly labelled. The example I gave was very simplified as there are many points within the loop in which the loop needs to be exited. Obviously I could achieve this with a while loop and set a boolean value, but I guess i just find the for loops easier as thats what i'm used to. I guess i just view it as a logical step up from a for each statement (as i'm looping through a 2d array). I'm currently just an amateur coder, perhaps if I get a job as one I'll have to reform my ways. :)
 
My opinion is that goto is 100% not necesary at any time (at least not in .Net).

I agree with that statement 100%.

Goto breeds spagetti - 1 goto here, 1 goto there - next thing you know you're going up and down the lines of code 20 times trying to figure out the program flow. Easier for you to read? Maybe now...leave it be for a month, come back and try to read it again and see if it's still easy. Easier for someone who doesn't know the program - by far no. There is a reason why the professional programming community has all but abandoned the 'goto' statement.

Personally I wish they would drop it from the langauge all together.
 
On another note with this whole break thing:

You have a for loop as follows:

C#:
for(int i=0;i<SomeCollection.Count;i++)
{
     if(SomeCollection[i]==SomeValue)
     {
           foundValue = SomeCollection[i];
           break;
     }
}

Say your collection has 1200 objects. Now when the for loop starts all 1200 objects are loaded onto the stack (or heap - whichever, it doesn't matter) and an enumerator is created.

Now the one you are looking for happens to be the fourth one - well you just allocated memory for 1196 objects for no reason, plus now whatever clean-up has to be done on those objects and the cost of the break statement itself.

Someone can probably correct me on my underlying process there - but I know it's something along those lines.

Regardless, these aren't an issue with a while loop as I have shown above.

Loops should be like database calls - get what you want and get out (don't return 10000 records if you're only going to use 100).

I hope that all makes some sort of since to someone who can explain it better :)
 
Well I'll be the first to admit I don't understand alot of programming concepts but what you've said has really confused me. You seem to be saying that when using the for loop the entire array will be loaded into memory but when using the while loop it won't. Yet I can't see a real conceptual difference. I could understand if the argument was a for each statement as this may very well load the entire array into memory, but I see nothing in a standard for loop that would make the system load the entire array into memory.

Using either method you are looping through a series of integers, accessing that index in an array then incrementing the index before repeating the process. This is all repeated untill the required object/ value is found. Maybe somebody else can shine some light on this and clarify what actually happens.

Oh and regarding the goto statement, yes if your using them all over the place then i could understand ppl getting confused. But using a statment similar to goto BreakLoop: reads no differntly to reading the line break; As with any other statement if used incorrectly it can screw up the readability of your program but this can be said of practically any statement.
 
The while loop increases the code to 8 code lines compared to the original 5 (ignoring whitespace etc.), adds an extra variable and increases the complexity of the escape expression and requires you to perform a manual increase on both loop counters rather than have the for loop do this implicitly.

Personally I find the use of goto in this situation provides a smaller code base with less likelyhood of simple errors (transposing i and j for example), and less likely to result in differing styles of code - note how the !requirmentMet appears as the 1st operand in one if statement and as the second in the other if statement in your sample.

Admittedly bickering over a couple of lines extra on such a small amount of code is petty (I never claimed I wasn't petty though ;)), however the alternating style of checking is either going to result in increased time to be consistent when writing the code or possible confusion when reading the code when the amount grows beyond what will comfortably fit on a single screen of information.

As a rule I would avoid the use of goto but that doesn't mean they do not have a valid use on occasion, and as long as the comments etc. explain and document the logic then I don't see a problem.

I most definately agree that code that relys heavily on goto will lead to difficult to maintain code especially if
  1. the flow is jumping up and down the routine.
  2. Jumping into a looping construct.
  3. Jumping into the middle of a flow control block.
  4. Jumping out of the current subroutine (for languages that support this)
however in this case one (or even a few gotos) that all jumped to a well named label immediately after the loop block isn't that hard to follow.

As I said before I would tend to be wary of any rules like this given as absolutes i.e. 'Never use goto' or 'Only have a single exit point from a function' as there are times when these rules do not benefit the code in any real way and breaking the rule will give cleaner more readable code.
 
Last edited:
Cags, I could be remember what I was told about how the two loops work internally incorrectly; I'll check with my senior and get back with you.
 
Okay, I appologize I was way off...don't know what recess of my brain that came from, but obviously had a memory leak or something and corrupt data - here's straight from the horse's mouth on what I've been taught about loops:

This is a good question. Unfortunately, I don't know that there's a purely technical reason for avoiding this. Here are some points to consider.


1. The original designers of the "for" loop structure intentionally did not design it to be broken. The "for" loop was specifically designed for use when a fixed number of items are to be iterated. If you anticipate the iterations terminating early (but normally), the while/until type loops are to be used. The "while" loop can be called the "conditional iterating structure".
2. There is nothing wrong, of course, with using conditionals inside of a loop, regardless of the loop type.
3. In keeping with #1 above, the "break" statement was actually added to languages (C, BASIC, etc.) later. Why are they bad? They are, essentially, an abbreviated GOTO statement. Why is GOTO bad? because it makes the code difficult to debug and maintenance isn't so easy.

With all that being said, the "break" statement is generally used in logical scenarios (such as the example you provided). That's not to say it's a good practice because someone could still use it poorly.

I guess I'm a bit old school but I like to think of it more like "right tool for the job". As such, I use "for" loops for fixed iterations and "while" loops for conditional iterations.
 
Back
Top