Meine Meinung: Komplexe Codeabläufe mit verschachtelten Schleifen sind schwer zu durchdenken; Verzweigungen, sei es mit goto oder break, machen es nur schwieriger. Anstatt das goto zu schreiben, würde ich zuerst gründlich darüber nachdenken, ob es eine Möglichkeit gibt, die verschachtelten Schleifen zu eliminieren.
Ein paar nützliche Techniken:
Erste Technik: Umwandlung der inneren Schleife in eine Methode. Die Methode soll zurückgeben, ob die äußere Schleife verlassen werden soll oder nicht. So:
for(outer blah blah blah)
{
for(inner blah blah blah)
{
if (whatever)
{
goto leaveloop;
}
}
}
leaveloop:
...
wird
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;
}
Zweite Technik: Wenn die Schleifen keine Seiteneffekte haben, verwenden Sie 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:
schreiben Sie stattdessen:
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);
Keine Schleifen, also kein Ausbrechen erforderlich.
Alternativ können Sie, wie der Konfigurator in einem Kommentar anmerkt, den Code auch in dieser Form schreiben:
var orderToFill = customers
.SelectMany(customer=>customer.Orders)
.Where(order=>!order.Filled)
.Where(order=>order.Total >= 100.00m)
.FirstOrDefault();
if (orderToFill != null) Fill(orderToFill);
Die Moral von der Geschicht': Schleifen betonen den Kontrollfluss auf Kosten der Geschäftslogik . Anstatt zu versuchen, immer komplexere Kontrollabläufe übereinander zu stapeln, sollten Sie versuchen, den Code so umzugestalten, dass die Geschäftslogik klar ist.