Ответ 1
Очень элегантным решением является перемещение всего гнезда петель на отдельный метод и return;
, когда вы хотите вырваться из всех циклов.
Возможный дубликат:
Вывод из вложенного цикла
У меня есть этот код
foreach (___)
{
foreach (___)
{
foreach (___)
{
if (condition)
{
//break out of all loops
}
}
}
}
Но break
только "разбивает" самый внутренний цикл (извините за мой английский), и я хочу оставить их всех...
Я думал о:
Есть ли более элегантный способ? как предоставлено С#?
Заранее благодарим за помощь!
Очень элегантным решением является перемещение всего гнезда петель на отдельный метод и return;
, когда вы хотите вырваться из всех циклов.
A goto
отлично здесь:
foreach (___)
{
foreach (___)
{
if (condition)
{
goto done;
}
}
}
done: ;
Лучший способ, вероятно, состоит в том, чтобы реорганизовать более мелкие методы с помощью операторов return. Но если вам нужно много переменных в области видимости, вы всегда можете использовать делегат.
Action work = delegate
{
foreach (___)
{
foreach (___)
{
foreach (___)
{
if (condition)
{
return;
}
}
}
}
};
work();
Несколько лет назад, когда я учился в школе, у нас была информатика с красивой книгой, глупый учитель. Одно правило - "нет". У меня был алгоритм с множеством циклов, который рос во много раз больше без goto.
Есть веские причины, и вырывание из нескольких циклов - это одно.
Возможно, это единственная действительная причина использования goto
.
bool bLoopBreak = false;
foreach (___)
{
foreach (___)
{
foreach (___)
{
if (condition)
{
bLoopBreak = true;
break;
//break out of all loops
}
}
if (bLoopBreak) break;
}
if (bLoopBreak) break;
}
Не бойтесь использовать goto
в таком случае. break
и continue
являются просто синтаксическим сахаром для goto
, и он экономно и правильно комментирует, что он может сделать код более понятным, чем множество вложенных проверок, чтобы увидеть, следует ли останавливать цикл.
PHP позволяет это сделать:
foreach (___)
{
foreach (___)
{
foreach (___)
{
break 3; // get out of all 3 loops
}
}
}
Я не очень много знаю о С#, но у него может быть аналогичная функция.
Просто, чтобы бросить альтернативу там: вы также можете выбросить исключение внутри цикла. В С#/Java/Python это разумно дешево. (В С++ не так много.)
Обратите внимание, что у Python есть исключение StopIteration
для аналогичного случая, так что это не неслыханно, хотя это может быть немного неортодоксальным в С# -land.;)
Иногда вы получаете исключение бесплатно, и поэтому его можно использовать, но лучше документировать его, если вы принимаете этот подход.
try {
foreach (___) {
foreach (___) {
if(your condition true) {
throw new IterationDone(); // or use a singleton to avoid allocating
}
}
}
// not found
catch (IterationDone e) {
// yay
}
Я сделал ответ на wiki сообщества, чтобы его можно было увидеть и обсудить. (Я не выступаю за это как первое и лучшее решение, это просто решение и, следовательно, заслуживает того, чтобы быть здесь...)