Break inner foreach loop and continue outer foreach loop

39,923

Solution 1

How about using a flag?

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

  DoStuff();
}

Solution 2

foreach(var item in items)
{
  foreach(var otheritem in otheritems)
  {
    if (!double.TryParse(otheritem))
    {
      //...
      goto nextUpperLoop;
    }
  }

  DoStuff();
  nextUpperLoop: ;
}

Solution 3

Begin by writing a better version of Double.TryParse:

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

OK, now you have something you can easily use to eliminate the inner loop entirely, so the problem goes away:

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

Rather than try to figure out how to move control around, just write code that looks like the logic. If the logic is "don't do stuff if any of the other items do not parse as doubles", then use the Any predicate to test all the other items to see if any of them do not parse as doubles. No loops, so no fancy loop control needed.

I would be inclined to go a step further; capture the logic in a query, and then iterate the query:

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

foreach(var goodItem in goodItems)
    DoStuff(goodItem);

Solution 4

Simple is best...

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

Another approach is to refactor:

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

The return ensures the DoStuff doesn't happen.

Solution 5

You need a variable to controll that and like you say.. do a 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();
}
Share:
39,923
Jon
Author by

Jon

Updated on December 16, 2020

Comments

  • Jon
    Jon over 3 years

    If I have a nested foreach loop how do I do break the inner loop and tell the outer to continue at that point without doing any other code below the inner loop?

    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();
    }
    
  • Merlyn Morgan-Graham
    Merlyn Morgan-Graham over 12 years
    The OP wants to skip the remaining code on the outer loop and continue its execution at the top of the outer loop.
  • arviman
    arviman almost 10 years
    This is probably the only legitimate use of goto. I prefer java's way of continuing by labelling for loops though.
  • arviman
    arviman almost 10 years
    @BLUEPIXY I was just ranting in the tiny hope that Anders will read this and implement it in the next version of C#. Hope, a man can.
  • arviman
    arviman almost 10 years
    @BLUEPIXY - Please stop being patronizing towards other community members. It's not like anyone's saying "there's no humour tag" with regard to your first comment. Thank you for your cooperation in making this community more friendly.
  • Kokodoko
    Kokodoko over 8 years
    Good advice, although it doesn't answer the question: how to break out of in inner loop, while continuing the outer? In this case you were able to simplify the code to a single loop, but that may not always be the case.