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:

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

故事的寓意:循环强调控制流程而牺牲业务逻辑.不要试图将越来越复杂的控制流堆叠在一起,而是尝试重构代码,以便明确业务逻辑.

相关文章
相关标签/搜索