是否可以打破嵌套循环?

P.B*_*key 7 javascript c#

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:
Run Code Online (Sandbox Code Playgroud)

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

Eri*_*ert 28

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

一些有用的技巧:

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

for(outer blah blah blah)
{
    for(inner blah blah blah)
    {
        if (whatever)
        {
             goto leaveloop;      
        }
    }
}
leaveloop:    
...
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

第二种技术:如果循环没有副作用,请使用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:    
Run Code Online (Sandbox Code Playgroud)

相反,写:

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);
Run Code Online (Sandbox Code Playgroud)

没有循环,因此不需要突破.

或者,正如配置程序在注释中指出的那样,您可以使用以下格式编写代码:

var orderToFill = customers
    .SelectMany(customer=>customer.Orders)
    .Where(order=>!order.Filled)
    .Where(order=>order.Total >= 100.00m)
    .FirstOrDefault();
if (orderToFill != null) Fill(orderToFill);
Run Code Online (Sandbox Code Playgroud)

故事的寓意:循环强调控制流程而牺牲业务逻辑.而不是试图堆在彼此顶部越来越复杂的控制流程,尝试重构代码,使业务逻辑清晰.


Jon*_*eet 12

我个人试图通过简单地将循环放入不同的方法来避免在这里使用goto - 虽然你不能轻易地突破特定级别的循环,但你可以在任何时候轻松地从方法返回.

根据我的经验,这种方法通常会导致更简单,更易读的代码和更短的方法(做一个特定的工作).


slu*_*ter 11

让我们直截了当:使用该goto语句没有任何根本性的错误,它不是邪恶的 - 它只是工具箱中的另一个工具.它是如何使用它真正重要的,它很容易被误用.

打破某些描述的嵌套循环可以有效地使用该语句,但您应首先查看它是否可以重新设计.您的循环退出表达式可以重写吗?你使用适当类型的循环?您是否可以过滤可能迭代的数据列表,以便您不需要提前退出?你应该将一些循环代码重构为一个单独的函数吗?


Thi*_*ter 5

IMO 在不支持break n;wheren指定应中断的循环数的语言中这是可以接受的。
至少它比设置一个变量然后在外循环中检查更具可读性。