如何在嵌套循环中终止外部循环?

Mir*_*ial 14 c# loops nested-loops

在下面的示例中,终止所有嵌套循环的最佳方法是什么.一旦if语句为true,我想终止外部for语句(使用I).换句话说,我需要整个循环停止.有没有比设置I更好的方法?

for (int I = 0; I < 10; I++)
{
    for (int A = 0; A < 10; A++)
    {
        for (int B = 0; B < 10; B++)
        {
            if (something)
                break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ell 32

我会将它重构为一个方法,并return在需要时随时调用.

你也可以使用goto,我已经习惯goto了这个,但它不受欢迎.哪个是愚蠢的; 这种情况是它存在于语言中的原因.

void DoSomeStuff()
{
    for (int I = 0; I < 10; I++)
    {
        for (int A = 0; A < 10; A++)
        {
            for (int B = 0; B < 10; B++)
            {
                if (something)
                    return;
            }
        }
    }
}
...somewhere else...
DoSomeStuff();
Run Code Online (Sandbox Code Playgroud)

  • @Mirial - 选择你想要的块; 在VS中,"提取方法" - 这就是重构的意思.现在你有一个方法可以"返回".基本上,你*可以*重构你的代码来做到这一点,你可能应该(听起来你的方法过长). (7认同)
  • @Mirial将代码重构为方法比使用goto更好. (3认同)
  • @Spolto:为什么? (2认同)

chr*_*aut 15

不要开枪,但这实际上可能需要一个转到:

 for (int I = 0; I < 10; I++) {
      for (int A = 0; A < 10; A++) {
           for (int B = 0; B < 10; B++) {
               if (something)
                   goto endOfTheLine;
            }
      }
  }
  endOfTheLine:
  Console.WriteLine("Pure evilness executed");
Run Code Online (Sandbox Code Playgroud)

  • 这正是goto是最佳解决方案的情况.它不会导致冗余条件检查的运行时开销,并且比到目前为止发布的所有备选方案更容易理解.现在goto最糟糕的缺点是其声誉不佳. (5认同)
  • 这实际上是`goto` IMO的合法用法. (4认同)

pax*_*blo 14

假设您要退出所有循环,您可以将其重构为更结构化的东西:

bool done = false;
for (int i = 0; i < 10 && !done; i++) {
    for (int a = 0; a < 10 && !done; a++) {
        for (int b = 0; b < 10 && !done; b++) {
            if (something) {
                done = true;
                continue;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Eri*_*ert 10

如果循环体不产生副作用,而只是寻找"某事物"为真的第一个值,那么将通过消除第一个地方的所有循环来解决问题.

var query = from I in Enumerable.Range(0, 10)
            from A in Enumerable.Range(0, 10)
            from B in Enumerable.Range(0, 10)
            where something(I, A, B)
            select new { I, A, B };
var result = query.FirstOrDefault();
if (result == null)
{
   Console.WriteLine("no result");
}
else
{
    Console.WriteLine("The first result matching the predicate was {0} {1} {2},
        result.I, result.A, result.B);
}
Run Code Online (Sandbox Code Playgroud)

但如果循环有副作用,请不要这样做; 查询是放置副作用的一个非常糟糕的地方.如果内循环有副作用,那么你可以这样做:

var triples = from I in Enumerable.Range(0, 10)
              from A in Enumerable.Range(0, 10)
              from B in Enumerable.Range(0, 10)
              select new { I, A, B };
foreach(var triple in triples)
{
    if (something(triple.I, triple.A, triple.B))
        break;
    DoSomeSideEffect(triple.I, triple.A, triple.B);
}
Run Code Online (Sandbox Code Playgroud)

现在只有一个循环可以突破,而不是三个.