1

Why can't I use a break; statement in a while loop, whilst in an anonymous method?

I was working on the piece of code (below), when I got this error: "Control cannot leave the body of an anonymous method or lambda expression".

Thankfully I can solve the problem by using return; instead, but I'd still like to know why I can't use break;. To me, the main difference between the two statements, was that return; exits a method, and break; exits the further-most nested loop.

My code,

while (someCondition)
{
    System.Threading.Thread.Sleep(500);

    Application.Current.Dispatcher.Invoke(new Action(() =>
    {
        if (someOtherCondition)
        {
            // Do stuff...
        }
        else
        {
            if (anotherCondition)
            {
                break;
            }

            // Do something else...
        }
    }));
}
Sam
  • 7,252
  • 16
  • 46
  • 65
  • 3
    Because you must exit your method first, and then you can exit your loop, and since anonymous methods are still methods, you have to exit it first – ppetrov Oct 16 '13 at 12:07
  • 1
    maybe this helps you: http://stackoverflow.com/questions/9070080/how-to-leave-the-body-of-a-lambda-expression – MUG4N Oct 16 '13 at 12:07
  • @ppetrov Right, so I would have to exit the method first (using `return;`), then `break;` the loop. – Sam Oct 16 '13 at 12:12
  • @Sam in theory yes, but in your specific case it would be more complicated, since you only want to break the loop if some conditions are met, so you'd have to find a way to get this information in your while loop – ppetrov Oct 16 '13 at 12:15
  • @Sam, yes you need to return, then break. To do that, change Action to Func for example and break on false being returned. – David Arno Oct 16 '13 at 12:16
  • @David Arno Ah ok, thanks. Or I suppose I could do [this](https://gist.github.com/ArcticWinter/7006863). – Sam Oct 16 '13 at 12:23
  • @Sam, nice use of a closure there. That's work just fine and I prefer it to my Func suggestion. – David Arno Oct 16 '13 at 12:28

5 Answers5

6

Rewriting the code helps to explain why:

while (someCondition)
{
    System.Threading.Thread.Sleep(500);

    Application.Current.Dispatcher.Invoke(MyMethod);
}

private void MyMethod()
{
    if (someOtherCondition)
    {
        // Do stuff...
    }
    else
    {
        if (anotherCondition)
        {
            break;
        }

        // Do something else...
    }
}

You are breaking inside a function that has no loop. The loop exists in another method. So return needs to be called instead, as you found out. Just because you are using an annonymous method, it's still a separate method to the one containing the while loop.

David Arno
  • 42,717
  • 16
  • 86
  • 131
5

For the same reason you can't do this:

while(1)
{
    method1();
}

void method1()
{
    break;
}

Even if your anonymous method is written in the same function as your while loop, it can still be called from somewhere where there isn't a while loop around.

ppetrov
  • 3,077
  • 2
  • 15
  • 27
2

break; cannot be used to exit methods, instead you need a return. And while inside a method your scope is limited to that method because it could have been called from anywhere. While inside the method there is no information on the calling scope and the code therefore does not know if there is a loop to break out of. So a method scope is different than the scope of an if-statement.

MrFox
  • 4,852
  • 7
  • 45
  • 81
0

Return takes you out of a method or a function but break gets you out of the loop or an iteration.

This is the main diff.

// This is Oki
public void Do()
{
  for (int i = 0; i < 10; i++)
  {
    break;        
  }
 }   

// This is a compiler error
public void Do()
{
    break;        
}       
Bassam Alugili
  • 16,345
  • 7
  • 52
  • 70
-2

You can change condition of while:

while (someCondition)
{
    System.Threading.Thread.Sleep(500);

    Application.Current.Dispatcher.Invoke(new Action(() =>
    {
        if (someOtherCondition)
        {
            // Do stuff...
        }
        else
        {
            if (anotherCondition)
            {
                //break;
                someCondition = false;
                return;
            }

            // Do something else...
        }
    }));
    if (!someCondition)
        break;
}
Ali Yousefi
  • 2,355
  • 2
  • 32
  • 47