14

After researching a way to exit a nested loop, I decided to try using goto,

private void example()
{
    for (int i = 0; i < 100; i++)
    {
        for (int ii = 0; ii < 100; ii++)
        {
            for (int iii = 0; iii < 100; iii++)
            {
                goto exitMethod;
            }                
        }             
    }

exitMethod:
}

But for some reason, if I put a goto label is at the very end of the method, Visual Studio 2012 (Ultimate) complains (and it won't compile),

Screenshot

But if I change my code to this,

private void example()
{
    for (int i = 0; i < 100; i++)
    {
        for (int ii = 0; ii < 100; ii++)
        {
            for (int iii = 0; iii < 100; iii++)
            {
                goto exitMethod;
            }                
        }             
    }

exitMethod:

    int someUnneededVariable; // Just an example, if I add ANY piece of code the error vanishes.
}

None of the errors appear (and it compiles); I've searched through all the MSDN references that I know of, and I couldn't find anything about this.

I know that I could easily solve this problem by using return;; even so, I would still like to find out what's causing this error.

Sam
  • 7,252
  • 16
  • 46
  • 65
  • 1
    I know; but it's the principle, from my understanding this should compile, but it doesn't. – Sam Aug 30 '13 at 14:27
  • 1
    @Sam: Nope, it really shouldn't :) – Jon Skeet Aug 30 '13 at 14:31
  • you should write some code after label. Or atlease ';' After label so that visual studio can understand that there is not more code after this. – Tushar Chhabhaiya Aug 30 '13 at 14:31
  • Why would you use something even though you never would or should...? – Austin T French Aug 30 '13 at 14:31
  • 4
    At least you survived the [raptor](http://xkcd.com/292/) attack! – Forty-Two Aug 30 '13 at 14:34
  • 1
    @AthomSfere: It's entirely reasonable to try to understand why some code wouldn't be valid. For example, `goto` can be useful in *autogenerated* code. (async/await *effectively* generates a bunch of gotos.) – Jon Skeet Aug 30 '13 at 14:36
  • It's like looking at a Windows 95 batch file. – Arran Aug 30 '13 at 14:37
  • @JonSkeet Ah, I see what you mean, I thought a goto label didn't need a statement to label to in order to work. Thanks for your post. – Sam Aug 30 '13 at 14:40
  • 1
    It's a shame we don't have named loops, then you could go `exit loop myOuterLoopName;` – Matthew Watson Aug 30 '13 at 14:42
  • This seems silly to me. There is an implied "return" statement at the closing curly brace, it is "there" whether we write a redundant statement, or even an empty statement (just a semicolon), or not. The end of a method is a perfectly valid place to jump to. Goto's CAN be used for temporary changes while debugging, that is perfectly valid also. The compiler should not fight you over non-substantive trivialities like this. It is smarter than that. Right? Why should just adding one semicolon to denote a null statement "fix" this code? What is gained? What would be lost if it was missing? –  Nov 06 '15 at 15:11
  • Related question - the accepted answer is basically the same as this question's code... http://stackoverflow.com/questions/6545720/does-anyone-still-use-goto-in-c-sharp-and-if-so-why –  Nov 06 '15 at 15:20

6 Answers6

20

A label doesn't exist on its own: it labels a statement. From section 8.4 of the C# 5 spec:

A labeled-statement permits a statement to be prefixed by a label. Labeled statements are permitted in blocks, but are not permitted as embedded statements.

In this case, you're applying the label at the end of the method - there's no statement for it to be a label for. So the compiler is absolutely right to reject your code.

If you really wanted to, you could add a label to an otherwise-redundant return statement:

exitMethod:
    return;
}

... or just an empty statement, as suggested by Irfan. There has to be a statement though.

But I wouldn't recommend it. Just change any goto exitMethod; statement to simply return.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
11

You can place blank statement.

Try:

exitMethod: ;            

But anyways, if you really want to return from current method, use return statement. if method has other return type than void,

return (type);

otherwise

return;
Irfan
  • 2,713
  • 3
  • 29
  • 43
1

In this case

goto exitMethod;

is equivalent to just plain

return;

and that plan return is significantly more readable. So I don't see why would you want to do that.

MK.
  • 33,605
  • 18
  • 74
  • 111
0

You need something for the goto to do. It cannot be blank.

For example:

private void example()
{
    for (int i = 0; i < 100; i++)
    {
        for (int ii = 0; ii < 100; ii++)
        {
            for (int iii = 0; iii < 100; iii++)
            {
                goto exitMethod;
            }                
        }             
    }

exitMethod:
    int i = DoSomething();
}
Sam Leach
  • 12,746
  • 9
  • 45
  • 73
  • Well, technically he is correct. The last instruction in the method is some kind of "return" instruction and there is no reason not to put a goto label before it. But why. – MK. Aug 30 '13 at 14:30
0
"The goto statement transfers the program control directly to a labeled statement." 

You have exitMethod as your label, but in your first example you have no statement. This is why you are getting an error.

goto reference

Paddyd
  • 1,870
  • 16
  • 26
-1

Two things, first goto is NOT recommended. It will not allow you to use a label like that because of how labels work. A label is a source code only identifier allowing you to point to a specific instruction. In the case you're attempting, there is no instruction following it, and thus it cannot resolve to the location of an instruction. This is causing your error.

Again, you shouldn't be using a goto in this way. If you simply need to exit the function, you can use a return; statement. If the coding standard you're using dictate only a single return point, then try something like this:

private void example()
{
    bool escaping = false;
    for (int i = 0; i < 100 && !escaping; i++)
    {
        for (int ii = 0; ii < 100 && !escaping; ii++)
        {
            for (int iii = 0; iii < 100 && !escaping; iii++)
            {
                escaping = true;
                break; // this is only needed if there is code farther down this 
                       // inner loop that would otherwise be executed.
            }                
        }             
    }

return;
}
Andrew Ring
  • 3,185
  • 1
  • 23
  • 28
  • If the OP wants to make a temporary change to the code while debugging it or modifying it, Goto is a useful temporary change to make. Your change is much harder. –  Nov 06 '15 at 15:15