是否可以打破嵌套循环? [英] Is goto ok for breaking out of nested loops?

查看:88
本文介绍了是否可以打破嵌套循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

JavaScript支持类似goto的语法来打破嵌套循环。一般来说这不是一个好主意,但它被认为是可以接受的做法。 C#不直接支持 break labelName 语法...但它确实支持臭名昭着的 goto

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 the break labelName syntax...but it does support the infamous goto.

我相信可以用C#实现等价物:

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:

同样JavaScript的逻辑,嵌套循环场景是 goto 的可接受用法?否则,我知道实现此功能的唯一方法是设置具有适当范围的 bool

By the same logic of JavaScript, is nested loop scenario an acceptable usage of goto? Otherwise, the only way I am aware to achieve this functionality is by setting a bool with appropriate scope.

推荐答案

我的观点:嵌套循环的复杂代码流很难推理;分支,无论是goto还是break,都会让它变得更难。我不会写goto,而是首先想到是否有办法消除嵌套循环。

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.

一些有用的技巧:

第一种技术:将内循环重构为方法。让方法返回是否突破外循环。所以:

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:    
...

变为

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

第二种技巧:如果循环没有副作用,请使用LINQ。

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:    

相反,写:

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.

这篇关于是否可以打破嵌套循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆