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

我相信可以在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

最佳答案

我的观点:带有嵌套循环的复杂代码流很难推理;分支,无论是goto还是break,都使它变得更加困难。首先,我会非常努力地思考是否有消除嵌套循环的方法,而不是编写goto。

几个有用的技术:

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

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

无循环,因此无需中断。

另外,正如配置器在注释中指出的那样,您可以使用以下形式编写代码:
var orderToFill = customers
    .SelectMany(customer=>customer.Orders)
    .Where(order=>!order.Filled)
    .Where(order=>order.Total >= 100.00m)
    .FirstOrDefault();
if (orderToFill != null) Fill(orderToFill);

故事的寓意:循环强调控制流,但以业务逻辑为代价。与其尝试使越来越复杂的控制流相互叠加,不如尝试重构代码以使业务逻辑清晰明了。

关于c# - goto是否可以打破嵌套循环?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7882451/

10-11 22:14
查看更多