Is goto ok for breaking out of nested loops?

后端 未结 10 1837
忘掉有多难
忘掉有多难 2021-01-18 04:33

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

相关标签:
10条回答
  • 2021-01-18 05:03

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

    0 讨论(0)
  • 2021-01-18 05:07

    I recommend using continue if you want to skip that one item, and break if you want to exit the loop. For deeper nested put it in a method and use return. I personally would rather use a status bool than a goto. Rather use goto as a last resort.

    0 讨论(0)
  • 2021-01-18 05:08

    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)
            {
                 return true;      
            }
        }
        return false;
    }
    

    Second technique: if the loops do not have 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:    
    

    instead, write:

    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);
    

    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.

    0 讨论(0)
  • 2021-01-18 05:08

    It's a bit of a unacceptable practice in C#. If there's no way your design can avoid it, well, gotta use it. But do exhaust all other alternatives first. It will make for better readability and maintainability. For your example, I've crafted one such potential refactoring:

    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;
    }
    
    0 讨论(0)
  • 2021-01-18 05:09
    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 讨论(0)
  • 2021-01-18 05:10

    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?

    0 讨论(0)
提交回复
热议问题