My opinion: it is difficult to describe complex code flows with nested loops; branching around, whether with goto or break, just makes it harder. Instead of writing goto, I would first think about whether there is a way to eliminate nested loops.
Some useful methods:
First method: reformat the inner loop to the method. Ask the method to return the exit or exit from 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) { return true; } } return false; }
Second method: if the loops have no side effects, use LINQ.
// fulfill the first unfulfilled order over $100 foreach(var customer in customers) { foreach(var order in customer.Orders) { if (!order.Filled && order.Total >= 100.00m) { Fill(order); goto leaveloop; } } } leaveloop:
write instead:
var orders = from customer in customers from order in customer.Orders; where !order.Filled where order.Total >= 100.00m select order; var orderToFill = orders.FirstOrDefault(); if (orderToFill != null) Fill(orderToFill);
There are no cycles, so no outputs are required.
Alternatively, as the coordinator points out in a comment, you can write 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 the flow of control through business logic . Instead of trying to build a more complex flow of control over each other, try refactoring the code so that the business logic is clear.
Eric Lippert
source share