7
while (foo() == true)
{
   foreach (var x in xs)
   {
       if (bar(x) == true)
       {
           //"break;" out of this foreach
           //AND "continue;" on the while loop.
       }
   }

   //If I didn't continue, do other stuff.
}

I'm a bit stuck on how to do this.


Update: I fixed the question. I left out the fact that I need to process other stuff if I don't call a continue; on the while loop.

Sorry, I didn't realize I used the word "something" twice.

myermian
  • 31,823
  • 24
  • 123
  • 215
  • 1
    just `break;` the while will continue because `something is true` – Djole Jul 15 '11 at 16:06
  • Sorry, I left something out. I need to be able to process additional items if I don't `continue;`. – myermian Jul 15 '11 at 16:08
  • then you need to either write `if(something)continue;` when you exit the `foreach` loop, or use `goto label` – Djole Jul 15 '11 at 16:11
  • 1
    Then edit the question so that it is clear! This question is very unclear. You are using "something" to mean two different things, it is very unclear where the necessary side effects are in these loops, and so on. It might be possible to rewrite this whole thing with no loops at all, or to refactor it into methods, or whatever, but without knowing what the actual problem is, it is difficult to say. – Eric Lippert Jul 15 '11 at 16:17
  • Oh, oops. I didn't even realize I used **something** twice. – myermian Jul 15 '11 at 16:20
  • Are `foo` and `bar` used only for their values, or do they also have a side effect? – Eric Lippert Jul 15 '11 at 16:36
  • @Eric: I guess I really shouldn't simplify this should I? Oh well, someone figured out what I needed and answered it. – myermian Jul 15 '11 at 17:11
  • @Eric: My previous comment meant that I shouldn't always try to simplify a question b/c this time I ended up using the same word for different meanings and left out an important part of the question. – myermian Jul 15 '11 at 19:58

6 Answers6

14

I would rewrite this:

while (foo() == true)
{
   foreach (var x in xs)
   {
       if (bar(x) == true)
       {
           //"break;" out of this foreach
           //AND "continue;" on the while loop.
       }
   }

   //If I didn't continue, do other stuff.
   DoStuff();
}

as

while (foo()) // eliminate redundant comparison to "true".
{
   // Eliminate unnecessary loop; the loop is just 
   // for checking to see if any member of xs matches predicate bar, so
   // just see if any member of xs matches predicate bar!
   if (!xs.Any(bar))        
   {
       DoStuff();
   }
}
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • This is nicer than what I was trying to do. :) – myermian Jul 15 '11 at 17:11
  • 4
    @myermian: A good rule of thumb that I try to use: if a loop is for *executing a particular side effect over and over again*, then use a loop. If a loop is solely for *computing a value*, then move the loop into a helper function, or find a helper function that already does what you want -- like "Any", or "All", or "Sum", or whatever. That way you make the loop an implementation detail of the helper, rather than a nested control flow of your method. – Eric Lippert Jul 15 '11 at 17:21
  • Yea, I didn't even think about the Any or All functions. But, it ended up helping a lot. I flipped the if so it `continue`s if it matches any and does the DoStuff() otherwise (Resharper agreed that inversing the if helps avoid nesting). This is way cleaner than having a bool value, setting it, breaking out of the for loop, checking the bool to see what the result was... – myermian Jul 15 '11 at 19:56
  • @myermian / eric: Out of curiosity, in what way is this different from my answer? – Ani Jul 16 '11 at 04:37
6
while (something)
{
   foreach (var x in xs)
   {
       if (something is true)
       {
           //Break out of this foreach
           //AND "continue;" on the while loop.
           break;
       }
   }
}
adrianos
  • 1,501
  • 2
  • 18
  • 22
4

If I understand you correctly, you can use the LINQ Any / All predicate here:

while (something)
{
    // You can also write this with the Enumerable.All method
   if(!xs.Any(x => somePredicate(x))
   {
      // Place code meant for the "If I didn't continue, do other stuff."
      // block here.
   }
}
Ani
  • 111,048
  • 26
  • 262
  • 307
2

This should address your requirement:

while (something)
{   
    bool doContinue = false;

    foreach (var x in xs)   
    {       
        if (something is true)       
        {           
            //Break out of this foreach           
            //AND "continue;" on the while loop.          
            doContinue = true; 
            break;       
        }   
    }

    if (doContinue)
        continue;

    // Additional items.
}

This sort of code happens frequently as soon as you need break to propagate through nested constructs. Whether it is a code smell or not is up for debate :-)

Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
0
while (something)
{
   foreach (var x in xs)
   {
       if (something is true)
       {
           break;
       }
   }
}

however, wouldn't both of these values always equate to true???

FiveTools
  • 5,970
  • 15
  • 62
  • 84
0

So you want to continue after breaking?

while (something)
{
    bool hit = false;

    foreach (var x in xs)
    {
        if (something is true)
        {
            hit = true;
            break;
        }
    }

    if(hit)
        continue;
}
Lourens
  • 1,510
  • 1
  • 13
  • 27