Подтвердить что ты не робот

Продолжить во вложенных циклах

В этом примере кода есть ли какой-нибудь способ продолжить по внешнему циклу из блока catch?

while
{
   // outer loop

   while
   {
       // inner loop
       try
       {
           throw;
       }
       catch 
       {
           // how do I continue on the outer loop from here?
           continue;
       }
   }
}
4b9b3361

Ответ 1

ОБНОВЛЕНИЕ: Этот вопрос был вдохновлен моей статьей по этому вопросу. Спасибо за отличный вопрос!


"continue" и "break" - не более чем приятный синтаксис для "goto". Видимо, давая им милые имена и ограничивая их использование конкретными контрольными структурами, они больше не набирают гнев "толпы всех годовиков - все плохо".

Если то, что вы хотите сделать, является продолжением-внешним, вы можете просто определить метку в верхней части внешнего цикла и затем "перейти" к этой метке. Если вы считаете, что это не мешает пониманию кода, это может быть наиболее целесообразным решением.

Однако я хотел бы рассмотреть это как возможность рассмотреть вопрос о том, будет ли ваш поток управления выгоден от некоторого рефакторинга. Всякий раз, когда у меня есть условные "break" и "continue" в вложенных циклах, я рассматриваю рефакторинг.

Рассмотрим:

successfulCandidate = null;
foreach(var candidate in candidates)
{
  foreach(var criterion in criteria)
  {
    if (!candidate.Meets(criterion)) // Edited.
    {  // TODO: no point in continuing checking criteria.
       // TODO: Somehow "continue" outer loop to check next candidate
    }
  }
  successfulCandidate = candidate;
  break;
}
if (successfulCandidate != null) // do something

Две методики рефакторинга:

Сначала извлеките внутренний цикл в метод:

foreach(var candidate in candidates)
{
  if (MeetsCriteria(candidate, criteria))
  { 
      successfulCandidate = candidate;
      break;
  }
}

Во-вторых, можно ли исключить все петли? Если вы зацикливаете, потому что пытаетесь найти что-то, а затем реорганизуйте его в запрос.

var results = from candidate in candidates 
              where criteria.All(criterion=>candidate.Meets(criterion))
              select candidate;
var successfulCandidate = results.FirstOrDefault();
if (successfulCandidate != null)
{
  do something with the candidate
}

Если нет циклов, тогда нет необходимости прерывать или продолжать!

Ответ 2

    while
    {
       // outer loop

       while
       {
           // inner loop
           try
           {
               throw;
           }
           catch 
           {
               // how do I continue on the outer loop from here?
               goto REPEAT;
           }
       }
       // end of outer loop
REPEAT: 
       // some statement or ; 
    }

Проблема решена. (что? Почему вы все так меня обманываете?)

Ответ 3

Вы можете использовать оператор break;.

while
{
   while
   {
       try
       {
           throw;
       }
       catch 
       {
           break;
       }
   }
}

"Продолжить" используется для перехода в верхнюю часть текущего цикла.

Если вам нужно вырвать больше уровней, вам придется либо добавить "если", либо использовать страшный/не рекомендуемый "goto".

Ответ 4

Поменяйте структуру try/catch внутренним циклом while:

while {
  try {
    while {
      throw;
    }
  }
  catch {
    continue;
  }
}

Ответ 5

Нет.
Я предлагаю, извлекая внутренний цикл в отдельный метод.

while
{
   // outer loop
       try
       {
           myMethodWithWhileLoopThatThrowsException()
       }
       catch 
       {
           // how do I continue on the outer loop from here?
           continue;
       }
   }
}

Ответ 6

Используйте break во внутреннем цикле.

Ответ 7

Вы просто хотите выйти из внутренней, которая будет продолжать внешний.

while
{
   // outer loop

   while
   {
       // inner loop
       try
       {
           throw;
       }
       catch 
       {
           // how do I continue on the outer loop from here?
           break;
       }
   }
}

Ответ 8

Я думаю, что лучший способ добиться этого - использовать инструкцию break. Разрыв завершает текущий цикл и продолжает выполнение с того места, где он заканчивается. В этом случае завершите внутренний цикл и , чтобы вернуться обратно во внешний цикл. Вот как выглядит ваш код:

while
{
   // outer loop

   while
   {
       // inner loop
       try
       {
           throw;
       }
       catch 
       {
           // break jumps to outer loop, ends inner loop immediately.
           break; //THIS IS THE BREAK
       }
   }
}

Я считаю, что это то, что вы искали, правильно? Спасибо!

Ответ 9

using System;

namespace Examples
{

    public class Continue : Exception { }
    public class Break : Exception { }

    public class NestedLoop
    {
        static public void ContinueOnParentLoopLevel()
        {
            while(true)
            try {
               // outer loop

               while(true)
               {
                   // inner loop

                   try
                   {
                       throw new Exception("Bali mu mamata");
                   }
                   catch (Exception)
                   {
                       // how do I continue on the outer loop from here?

                       throw new Continue();
                   }
               }
            } catch (Continue) {
                   continue;
            }
        } 
    }

}

}

Ответ 10

Используйте собственный тип исключения, например MyException. Тогда:

while
{
   try {
   // outer loop
   while
   {
       // inner loop
       try
       {
           throw;
       }
       catch 
       {
           // how do I continue on the outer loop from here?
           throw MyException;
       }
   }
   } catch(MyException)
   { ; }
}

Это будет работать для продолжения и выхода из нескольких уровней вложенных показов. Извините за плохое форматирование;)