Skip to content Skip to sidebar Skip to footer

Is Goto Ok For Breaking Out Of Nested Loops?

JavaScript supports a goto like syntax for breaking out of nested loops. It's not a great idea in general, but it's considered acceptable practice. C# does not directly support t

Solution 1:

My opinion: complex code flows with nested loops are hard to reason about; branching around, whether it is with goto or break, just makes it harder. Rather than writing the goto, I would first think really hard about whether there is a way to eliminate the nested loops.

A couple of useful techniques:

First technique: Refactor the inner loop to a method. Have the method return whether or not to break out of the outer loop. So:

for(outer blah blah blah)
{
    for(inner blah blah blah)
    {
        if (whatever)
        {
             goto leaveloop;      
        }
    }
}
leaveloop:    
...

becomes

for(outer blah blah blah)
{
    if (Inner(blah blah blah))
        break;
}

...

bool Inner(blah blah blah)
{
    for(inner blah blah blah)
    {
        if (whatever)
        {
             returntrue;      
        }
    }
    returnfalse;
}

Second technique: if the loops do not have side effects, use LINQ.

// fulfill the first unfulfilled order over $100foreach(var customer in customers)
{
    foreach(var order in customer.Orders)
    {
        if (!order.Filled && order.Total >= 100.00m)
        {
             Fill(order);
             goto leaveloop;      
        }
    }
}
leaveloop:    

instead, write:

var orders = from customer in customers
             fromorderin customer.Orders;
             where !order.Filled
             whereorder.Total >= 100.00m
             selectorder;
var orderToFill = orders.FirstOrDefault();
if (orderToFill != null) Fill(orderToFill);

No loops, so no breaking out required.

Alternatively, as configurator points out in a comment, you could write the code in this form:

var orderToFill = customers
    .SelectMany(customer=>customer.Orders)
    .Where(order=>!order.Filled)
    .Where(order=>order.Total >= 100.00m)
    .FirstOrDefault();
if (orderToFill != null) Fill(orderToFill);

The moral of the story: loops emphasize control flow at the expense of business logic. Rather than trying to pile more and more complex control flow on top of each other, try refactoring the code so that the business logic is clear.

Solution 2:

I would personally try to avoid using goto here by simply putting the loop into a different method - while you can't easily break out of a particular level of loop, you can easily return from a method at any point.

In my experience this approach has usually led to simpler and more readable code with shorter methods (doing one particular job) in general.

Solution 3:

Let's get one thing straight: there is nothing fundamentally wrong with using the goto statement, it isn't evil - it is just one more tool in the toolbox. It is how you use it that really matters, and it is easily misused.

Breaking out of a nested loop of some description can be a valid use of the statement, although you should first look to see if it can be redesigned. Can your loop exit expressions be rewritten? Are you using the appropriate type of loop? Can you filter the list of data you may be iterating over so that you don't need to exit early? Should you refactor some loop code into a separate function?

Solution 4:

IMO it is acceptable in languages that do not support break n; where n specifies the number of loops it should break out. At least it's much more readable than setting a variable that is then checked in the outer loop.

Solution 5:

I believe the 'goto' is acceptable in this situation. C# does not support any nifty ways to break out of nested loops unfortunately.

Post a Comment for "Is Goto Ok For Breaking Out Of Nested Loops?"