为什么我不能在方法结尾处添加goto标签?

14

在研究如何退出嵌套循环后,我决定尝试使用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:
}

但出于某些原因,如果我将goto标签放在方法的末尾,Visual Studio 2012(终极版)会抱怨(并且它将无法编译),

屏幕截图

但是如果我改成这样:

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.
}

没有出现错误(可以编译);我已经搜索了我所知道的所有MSDN参考资料,但我找不到任何关于这个的信息。

我知道我可以轻松通过使用return;来解决这个问题;即便如此,我仍然想找出是什么导致了这个错误。


1
我知道,但这是原则问题。据我理解,这段代码应该可以编译通过,但实际上却没有。 - Sam
1
@Sam:不,这确实不应该 :) - Jon Skeet
4
你至少幸存了下来,避免被迅猛龙攻击! - Forty-Two
1
@AthomSfere:尝试理解某些代码为什么无效是完全合理的。例如,在自动生成的代码中,goto可能很有用。(async/await 有效地生成了一堆goto语句。) - Jon Skeet
1
很遗憾我们没有命名循环,否则你可以使用 exit loop myOuterLoopName; - Matthew Watson
显示剩余6条评论
7个回答

20
并不是独立存在的,它用来给一个语句加上标记。引自C# 5规范的8.4节:

标记语句允许在语句前添加标记。标记语句在块中被允许,但不能作为嵌套语句。

在这种情况下,您将标签应用在方法的末尾,但没有语句可以被它所标记。因此编译器拒绝了您的代码是完全正确的。

如果您确实想这么做,您可以在无意义的返回语句上添加一个标签:

exitMethod:
    return;
}

...或者只是一个空语句,如Irfan所建议的。不过必须要有一个语句。

但我不建议这样做。只需将任何goto exitMethod;语句更改为简单的return即可。


11

你可以放置一个空语句。

尝试:

exitMethod: ;            

不管怎样,如果你真的想从当前方法返回,请使用return语句。 如果方法具有除void以外的其他返回类型,

return (type);

否则

return;

1
在这种情况下。
goto exitMethod;

等同于普通文本

return;

而且这个计划的返回值更易读。所以我不明白为什么你要这样做。


0
你缺少了一个分号 试试这个:
exitMethod:;

感谢您成为社区的贡献者!您的答案似乎是正确的。然而,请注意,几年前已经有另一个回答给出了完全相同的建议。一个好的答案还应该提供背景信息。例如,不仅仅提供一个答案,还要详细说明为什么它有效。 - undefined

0

你需要为 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:
    int i = DoSomething();
}

他从技术上讲是正确的。方法中的最后一条指令是某种“返回”指令,没有理由不在它之前放置一个goto标签。但是为什么呢? - MK.

0
"The goto statement transfers the program control directly to a labeled statement." 

你的标签是exitMethod, 但在第一个例子中你没有语句。这就是为什么你会得到一个错误。

跳转到参考


-1

首先,不建议使用goto。这是因为标签的工作方式不允许您像这样使用标签。标签是仅限于源代码的标识符,允许您指向特定指令。在您尝试的情况下,没有指令跟随它,因此无法解析到指令的位置。这会导致错误。

再次强调,在此情况下不应该使用goto。如果您只需要退出函数,则可以使用“return;”语句。如果您使用的编码标准规定必须有单个返回点,则可以尝试类似以下方式:

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;
}

如果 OP 想在调试或修改代码时进行临时更改,Goto 是一个有用的临时更改。你的更改要困难得多。 - user4624979

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接