中断内部foreach循环并继续外部foreach循环

本文关键字:foreach 循环 外部 继续 中断 内部 | 更新日期: 2023-09-27 18:14:53

如果我有一个嵌套的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();
}

中断内部foreach循环并继续外部foreach循环

如何使用标志?

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

从编写一个更好的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);

简单为上品

  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不会发生

你需要一个变量来控制它,就像你说的…做一个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();
}
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();
}

a break;语句只会中断最近的循环,所以发出break;

从您的代码片段中不清楚,但如果您只需要在otheritems中寻找不可解析的值,那么您可以使用LINQ:

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