【问题标题】:Break inner foreach loop and continue outer foreach loop中断内部 foreach 循环并继续外部 foreach 循环
【发布时间】:2011-11-17 14:17:10
【问题描述】:

如果我有一个嵌套的 foreach 循环,我该如何打破内循环并告诉外循环在该点继续,而不在内循环下面执行任何其他代码?

foreach(var item in items)
{
  foreach(var otheritem in otheritems)
  {
    if (!double.TryParse(otheritem))
    {
      //break inner loop
      //continue outer loop so we never get to DoStuff()
    }
  }

  DoStuff();
}

【问题讨论】:

  • 我注意到这不是 double.TryParse 的签名。

标签: c# .net c#-4.0 .net-4.0


【解决方案1】:

使用旗帜怎么样?

foreach(var item in items)
{
  bool flag = false;
  foreach(var otheritem in otheritems)
  {
    if (!double.TryParse(otheritem))
    {
        flag = true;
        break;
    }
  }
  if(flag) continue;

  DoStuff();
}

【讨论】:

    【解决方案2】:
    foreach(var item in items)
    {
      foreach(var otheritem in otheritems)
      {
        if (!double.TryParse(otheritem))
        {
          //...
          goto nextUpperLoop;
        }
      }
    
      DoStuff();
      nextUpperLoop: ;
    }
    

    【讨论】:

    • 这可能是 goto 的唯一合法用途。不过,我更喜欢 java 通过标记 for 循环来继续的方式。
    • @BLUEPIXY 我只是在咆哮,希望 Anders 能够阅读并在下一版本的 C# 中实现它。希望,男人可以。
    • @BLUEPIXY - 请停止光顾其他社区成员。对于您的第一条评论,这不像任何人所说的“没有幽默标签”。感谢您的合作,让这个社区变得更加友好。
    【解决方案3】:

    从编写更好的 Double.TryParse 版本开始:

    static double? TryParseDouble(this string s)
    {
        double d;
        return double.TryParse(s, out d) ? (double?)d : (double?)null;
    }
    

    好的,现在您可以轻松地使用一些东西来完全消除内部循环,所以问题就消失了:

    foreach(var item in items)
        if (!otheritems.Any(otherItem=>otherItem.TryParseDouble() == null))
            DoStuff();
    

    与其试图弄清楚如何移动控制,只需编写看起来像逻辑的代码。如果逻辑是“如果任何其他项目不解析为双精度则不做任何事情”,则使用 Any 谓词测试所有其他项目以查看它们中的任何项目是否不解析为双精度。没有循环,因此不需要花哨的循环控制。

    我倾向于更进一步;捕获查询中的逻辑,然后迭代查询:

    var goodItems = from item in items
                    where !item.OtherItems.Any(otherItem=>otherItem.TryParseDouble() == null))
                    select item;
    
    foreach(var goodItem in goodItems)
        DoStuff(goodItem);
    

    【讨论】:

    • 好建议,虽然它没有回答问题:如何在内部循环中跳出,同时继续外部循环?在这种情况下,您可以将代码简化为单个循环,但情况可能并非总是如此。
    【解决方案4】:

    简单就是最好的...

      bool doStuff = true;
      foreach(var otheritem in otheritems)
      {
        if (!double.TryParse(otheritem))
        {
            doStuff = false;
            break;
        }
      }
      if(doStuff) DoStuff();
    

    另一种方法是重构:

    foreach(var outerItem in outerLoop) {
         Foo(outerItem);
    }
    ...
    void Foo(OuterItem item) {
        foreach(var innerItem in innerLoop) {
            if(someTest) return;
        }
        DoStuff();
    }
    

    return 确保DoStuff 不会发生。

    【讨论】:

      【解决方案5】:

      你需要一个变量来控制它,就像你说的那样......做一个break

      bool doStuff = true;
      foreach(var item in items)
      {
        doStuff = true;
        foreach(var otheritem in otheritems)
        {
          if (!double.TryParse(otheritem))
          {
            doStuff = false;
            break;
          }
        }
      
        if (doStuff)
             DoStuff();
      }
      

      【讨论】:

        【解决方案6】:
        foreach(var item in items)
        {
          var shouldContinue = false;
        
          foreach(var otheritem in otheritems)
          {
            if (!double.TryParse(otheritem))
            {
              shouldContinue = true;
              //break inner loop
              //continue outer loop so we never get to DoStuff()
            }
          }
        
          if(shouldContinue)
             continue;
        
          DoStuff();
        }
        

        【讨论】:

          【解决方案7】:

          休息一下;语句只会中断最近的循环,所以发出一个break;在内循环中应该继续外循环中的下一项。

          【讨论】:

          • OP 想要跳过外循环的剩余代码并在外循环的顶部继续执行。
          【解决方案8】:

          从您的 sn-p 中不清楚,但如果您只需要在 otheritems 中查找不可解析的值,那么您可以使用 LINQ:

          foreach(var item in items)
          {
            bool shouldISkip = otheritems.Any(otherItem => !double.TryParse(otherItem));
            if(shouldISkip) continue;
            DoStuff();
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-09-04
            • 2023-04-09
            • 2022-08-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多