退出多个循环

本文关键字:循环 退出 | 更新日期: 2023-09-27 18:20:35

可能重复:
打破嵌套循环

我有这个代码

foreach (___)
{
    foreach (___)
    {
        foreach (___)
        {
            if (condition)
            {
                //break out of all loops
            }
        }
    }
}

break只"打破"了最核心的循环(对不起我的英语),我想把它们都留下。。。

我在想:

  1. GOTO,但我一直被告知不要使用它
  2. 一种布尔标志

还有什么更优雅的方式吗?像C#提供的那样?

提前感谢您的帮助!

退出多个循环

一个非常优雅的解决方案是,当您想要中断所有循环时,将整个循环嵌套移动到一个单独的方法和return;

goto在这里非常好:

foreach (___)
{
    foreach (___)
    {
        if (condition)
        {
            goto done;
        }
    }
}
done: ;

最好的方法可能是用返回语句重构到更小的方法。但是,如果您在作用域中需要大量变量,则可以始终使用委托。

   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;
}

在这种情况下不要害怕使用gotobreakcontinue只是goto的语法糖,而且注释谨慎且正确——它可以使代码比许多嵌套检查更清晰,以查看是否应该停止循环。

PHP可以让你做到这一点:

foreach (___)
{
    foreach (___)
    {
        foreach (___)
        {
            break 3; // get out of all 3 loops
        }
    }
}

我对C#了解不多,但它可能有类似的功能。

只是在其中抛出一个替代方案:您也可以在循环中抛出一个异常。在C#/Java/Python中,这样做相当便宜。(在C++中,没有那么多。)

请注意,对于类似的情况,Python有一个StopIteration异常,所以这并非闻所未闻,尽管它在C#中可能有点非正统。)

有时,您可以免费获得异常,因此可以使用它,但如果您采用这种方法,您最好将其记录下来。

try {
    foreach (___) {
        foreach (___) {
            if(your condition true)  {
                throw new IterationDone(); // or use a singleton to avoid allocating
            }
        }
    }
    // not found
catch (IterationDone e) {
    // yay    
}

我把这个答案做成了一个社区维基,这样它就可以被看到和讨论了。(我不主张它是第一个也是最好的解决方案,它只是一个解决方案,因此值得在这里…)