在嵌套的while循环中继续

Sku*_*ner 55 c# loops continue while-loop

在这个代码示例中,有没有办法从catch块继续外部循环?

while
{
   // outer loop

   while
   {
       // inner loop
       try
       {
           throw;
       }
       catch 
       {
           // how do I continue on the outer loop from here?
           continue;
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 101

更新:这个问题是我关于这个主题的文章的灵感来源.谢谢你这个好问题!


"继续"和"休息"只不过是一个"goto"的愉快语法.显然,通过给他们可爱的名字并将他们的用法限制在特定的控制结构中,他们不再引起"所有人一直都很糟糕"的愤怒.

如果您想要做的是继续到外部,您可以简单地在外部循环的顶部定义标签,然后"转到"该标签.如果您认为这样做并不妨碍代码的可理解性,那么这可能是最方便的解决方案.

但是,我会以此为契机,考虑您的控制流是否会受益于某些重构.每当我在嵌套循环中有条件"break"和"continue"时,我都会考虑重构.

考虑:

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

两种重构技术:

首先,将内循环提取到一个方法:

foreach(var candidate in candidates)
{
  if (MeetsCriteria(candidate, criteria))
  { 
      successfulCandidate = candidate;
      break;
  }
}
Run Code Online (Sandbox Code Playgroud)

其次,可以消除所有循环吗?如果您正在尝试搜索某些内容而进行循环,则将其重构为查询.

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
}
Run Code Online (Sandbox Code Playgroud)

如果没有循环,则无需中断或继续!

  • +1为"...将内循环提取到方法".当我看到嵌套循环时,我在代码审查中需要很多理由.它们通常会损害可读性,可维护性和稳定性.OP的问题可以通过简单的"返回"或"抛出"来解决(因此不以任何方式依赖于gotos). (8认同)
  • 绝对.当你认为你需要一个'goto`时,先停下片刻,然后思考你是否真的这么做.如果你仍然需要一个`goto`,那么就使用它 - 因为某种原因它在语言中.它本身也不是邪恶的 - 它通常只出现在邪恶的模式中,因此应该作为一个停止并试图发现这种模式的信号(而不是陷入"OMG`goto`这是完全错误的"恐慌). (8认同)
  • Goto 本质上并不是邪恶的,但它是通往糟糕、懒惰代码的门户毒品。在所有控制流量的方法中,它“通常”是最糟糕的。 (2认同)
  • 不要忘记为第二次重构技术添加`using System.Linq`. (2认同)
  • 如此冗长,哪里像 Java 一样 continue {nameOfLoop} .. :-( (2认同)

rya*_*ack 33

    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 ; 
    }
Run Code Online (Sandbox Code Playgroud)

问题解决了.(什么?你们为什么都给我这么脏的样子?)

  • 除非你明确地添加一个空语句分号(`REPEAT:;`),否则可能无法编译 (4认同)
  • 我明白你在那里做了什么 (3认同)

Jak*_*son 19

你可以休息一下; 声明.

while
{
   while
   {
       try
       {
           throw;
       }
       catch 
       {
           break;
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

Continue用于跳回当前循环的顶部.

如果你需要打破更多的级别,你将需要添加某种'if'或使用可怕的/不推荐的'goto'.

  • 这个方法的问题是如果在内部循环结束和外部循环结束之间需要完成额外的工作,它将在调用`break`时完成,但在调用时不会完成continue`.如果您需要不执行该代码,则需要一个标志.我不是说这个答案是错的(哎呀,我赞成它),我说这看起来很简单. (2认同)

Wel*_*bog 10

使用内部while循环交换try/catch结构:

while {
  try {
    while {
      throw;
    }
  }
  catch {
    continue;
  }
}
Run Code Online (Sandbox Code Playgroud)


sha*_*esh 5

不,
我建议将内部循环提取到一个单独的方法中。

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

  • 这就是微软给我们函数参数的原因。 (6认同)
  • 您也不应该将异常处理过程用于正常的代码控制流 (3认同)