我的观点:带有嵌套循环的复杂代码流很难推理;分支,无论是使用 goto 还是break,只会让事情变得更加困难。我不会编写 goto,而是首先认真思考是否有办法消除嵌套循环。
一些有用的技巧:
第一种技术:将内部循环重构为方法。让方法返回是否跳出外循环。所以:
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;
}
第二种技术:如果循环没有副作用,请使用 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);
这个故事的主旨:循环强调控制流,但牺牲了业务逻辑。与其尝试将越来越复杂的控制流堆叠在一起,不如尝试重构代码以使业务逻辑清晰。