Is there any approval for exiting nested loops?

JavaScript supports goto syntax for exiting nested loops. This is not a great idea in general, but it considers acceptable practice. C # does not directly support the break labelName syntax ... but it does support the infamous goto .

I believe the equivalent can be achieved in C #:

  int i = 0; while(i <= 10) { Debug.WriteLine(i); i++; for(int j = 0; j < 3; j++) if (i > 5) { goto Break;//break out of all loops } } Break: 

By the same JavaScript logic, is a nested loop script acceptable using goto ? Otherwise, the only way I know to achieve this functionality is to install bool with the appropriate scope.

+8
javascript c #
source share
9 answers

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.

+26
source share

I personally would try to avoid using goto here by simply placing the loop in another method - while you cannot easily break out of a certain level of the loop, you can easily return from the method at any point.

In my experience, this approach usually led to a simpler and more understandable code with shorter methods (doing one specific job) as a whole.

+12
source share

Let’s get one thing straight: there’s nothing fundamentally wrong with using the goto , it’s not evil - it’s just another tool in the toolbar. This is how you use it , which is really important, and it's easy to use.

Deriving some description from the nested loop may be a valid use of the operator, although you must first see if it can be redesigned. Is it possible to overwrite loop expressions? Are you using the appropriate type of loop? Can you filter out a list of data that you can iterate over so you don't have to exit earlier? Should you reorganize any loop code into a separate function?

+10
source share

IMO is acceptable in languages ​​that do not support break n; , where n indicates the number of cycles that it should break out.
At least this is much more readable than setting a variable, which is then checked in an outer loop.

+4
source share

I think that "goto" is acceptable in this situation. C # does not support any great ways to exit nested loops, unfortunately.

+2
source share

This is a bit unacceptable practice in C #. If you cannot avoid this, you should use it. But first release all the other alternatives. This will provide better readability and ease of maintenance. For your example, I created one such refactoring method:

 void Original() { int i = 0; while(i <= 10) { Debug.WriteLine(i); i++; if (Process(i)) { break; } } } bool Process(int i) { for(int j = 0; j < 3; j++) if (i > 5) { return true; } return false; } 
+2
source share

Unacceptable in C #.

Just wrap the loop in a function and use return .

EDIT: On SO, downvoting is used for incorrect answers, not for answers you disagree with. Since the OP directly asks “is this acceptable?”, The answer is “unacceptable” is incorrect (although you may disagree).

0
source share

I recommend using continue if you want to skip this element and break if you want to exit the loop. For a deeper nested, enter it into a method and use return . I personally would rather use bool status than goto . Rather, use goto as a last resort.

0
source share
 int i = 0; while(i <= 10) { Debug.WriteLine(i); i++; for(int j = 0; j < 3 && i <= 5; j++) { //Whatever you want to do } } 
0
source share

All Articles