Продолжить во вложенных циклах
В этом примере кода есть ли какой-нибудь способ продолжить по внешнему циклу из блока catch?
while
{
// outer loop
while
{
// inner loop
try
{
throw;
}
catch
{
// how do I continue on the outer loop from here?
continue;
}
}
}
Ответы
Ответ 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)
{ ; }
}
Это будет работать для продолжения и выхода из нескольких уровней вложенных показов.
Извините за плохое форматирование;)