从开关块中断开foreach循环

Dea*_*uga 57 .net c#

如何在开关区内摆脱foreach循环?

通常,你使用break但是如果你在switch块中使用break,它只会让你离开switch块而foreach循环将继续执行:

foreach (var v in myCollection)
{
    switch (v.id)
    {
        case 1:
            if (true)
            {
                break;
            }
            break;
        case 2;
            break
    }
}
Run Code Online (Sandbox Code Playgroud)

当我需要foreachswitch块内打破时,我正在做的是将bool循环外的值设置为true,并在每次foreach输入和进入开关块之前检查此bool的值.像这样的东西:

bool exitLoop;
foreach (var v in myCollection)
{
    if (exitLoop) break;
    switch (v.id)
    {
        case 1:
            if (true)
            {
                exitLoop = true;
                break;
            }
            break;
        case 2;
            break
    }
}
Run Code Online (Sandbox Code Playgroud)

这有效,但我一直认为必须有一个更好的方法这样做我不知道...

编辑:想知道为什么这不是在.NET中实现它在PHP中工作的非常简洁的方式@jon_darkstar提到的?

$i = 0;
while (++$i) {
    switch ($i) {
    case 5:
        echo "At 5<br />\n";
        break 1;  /* Exit only the switch. */
    case 10:
        echo "At 10; quitting<br />\n";
        break 2;  /* Exit the switch and the while. */
    default:
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

Ree*_*sey 64

在这种情况下,您的解决方案几乎是最常见的选择.话虽这么说,我会在最后进行退出检查:

bool exitLoop;
foreach (var v in myCollection)
{
    switch (v.id)
    {
        case 1:
            if (true)
            {
                exitLoop = true;
            }
            break;
        case 2;
            break
    }

    // This saves an iteration of the foreach...
    if (exitLoop) break;
}
Run Code Online (Sandbox Code Playgroud)

另一个主要选项是重构代码,并将switch语句和foreach循环拉出到单独的方法中.然后你可以return从switch语句里面.


sir*_*ide 25

布尔值是单向的.另一个是使用标签和转到.我知道人们认为goto是一个主要的罪恶,但明智地使用(非常明智地),它可能是有用的.在这种情况下,将标签放在foreach循环的末尾.如果要退出循环,只需转到该标签即可.例如:

foreach(var v in myCollection) {
    switch(v.Id) {
        case 1:
            if(true) {
                goto end_foreach;
            }
            break;
        case 2:
            break;
    }
}
end_foreach:
// ... code after the loop
Run Code Online (Sandbox Code Playgroud)

编辑:有些人提到将循环放入一个单独的方法,以便您可以使用返回.我看到了这个的好处,因为它不需要goto,它还简化了包含循环的原始函数.但是,如果循环很简单并且是包含它的函数的主要目的,或者循环使用out或ref变量,那么最好将它保留到位并使用goto.事实上,因为goto和标签脱颖而出,它可能使代码更清晰而不是笨拙.将它放在一个单独的函数中可能会使简单的代码更难阅读.

  • 我认为拥有一千个小功能会掩盖整体情况.我知道它在硬核OO圈子中风靡一时,但是我发现通过一系列功能进行探索,这些功能的存在纯粹是由于"从不使用goto"这样的原因比处理单个稍长但相干的功能要困难得多. . (11认同)
  • 如果你说'为什么*goto会让代码变得更复杂,那就更好了,特别是当替代方案同样复杂并且使代码远离其原始上下文时. (8认同)
  • 不要使用转到.它使代码更复杂.提取方法要好得多. (6认同)
  • @Andrew制作一个简短的函数,只能从一个地方调用,唯一的目的是能够返回中间函数,这不是一个比`goto`更好的解决方案.除了反驳民意之外,你还没有证明你的反goto情绪. (6认同)
  • 我很确定.NET架构师不会在框架中包含goto,如果他们觉得没有合法的用途,虽然这可能就是这种情况我仍然宁愿把循环拉成一个单独的方法作为使用旗帜的替代方法...... (3认同)
  • @siride 这本书没有提到 goto。它说的是编写易于维护和理解的清晰代码。当您编写代码时 goto 更容易理解时,我只是看不到任何情况。 (2认同)

And*_*zub 17

您可以将foreach循环提取到单独的方法并使用return语句.或者你可以这样做:

        foreach (object collectionElement in myCollection)
        {
            if (ProcessElementAndDetermineIfStop(collectionElement))
            {
                break;
            }
        }

        private bool ProcessElementAndDetermineIfStop(object collectionElement)
        {
            switch (v.id)
            {
                case 1:
                    return true; // break cycle.
                case 2;
                    return false; // do not break cycle.
            }
        }
Run Code Online (Sandbox Code Playgroud)


mea*_*gar 10

说实话?这可能是唯一完全有效且适当使用的情况goto:

foreach (var v in myCollection) {
    switch (v.id) {
        case 1:
            if (true)
                // document why we're using goto
                goto finished;
            break;
        case 2;
            break
    }
}
finished: // document why I'm here
Run Code Online (Sandbox Code Playgroud)

  • 它会引起什么疼痛?返回和中断有效地做同样的事情,除了没有明确的标签,可能使代码可读性降低.反goto鸭子需要死.从程序编程之前的日子开始,人们会真正地写出意大利面条代码而不是其他东西.现在我们主要使用更高级别的构造,偶尔的goto根本不是问题.反g h歇斯底里只不过是货物崇拜节目,AFAIC. (4认同)
  • 为什么在你可以转到时提取方法?它真的是六合一,半打另一半.如果循环小到足以首先属于单个函数,那么重构它似乎有点奇怪以避免干净和清晰的goto. (3认同)
  • @Andrew*miss-use*of goto会导致痛苦,对于任何语言结构都可以这么说. (3认同)
  • 为什么要使用goto?提取方法要好得多.每次使用goto语句时,小猫都会死亡. (2认同)
  • 我参加这个聚会晚了 7 年,但我完全同意@siride。“goto 杀死小猫”的神话必须结束。 (2认同)

dah*_*byk 6

它与你的exitLoop旗帜并没有什么不同,但是如果你提取一个方法它可能更具可读性......

foreach (var v in myCollection)
{
    if(!DoStuffAndContinue(v))
        break;
}


bool DoStuffAndContinue(MyType v)
{
    switch (v.id)
    {
        case 1:
            if (ShouldBreakOutOfLoop(v))
            {
                return false;
            }
            break;
        case 2;
            break;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)


Kla*_*sen 5

总是可以选择重构您的代码,以便您可以returnswitch声明中进行.