【问题标题】:Why can't I add a goto label at the end of a method?为什么我不能在方法末尾添加 goto 标签?
【发布时间】:2013-08-30 14:25:44
【问题描述】:

在研究了退出嵌套循环的方法后,我决定尝试使用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 (Ultimate) 会报错(并且无法编译),

但是如果我把我的代码改成这个,

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; 可以轻松解决这个问题;即便如此,我仍然想找出导致此错误的原因。

【问题讨论】:

  • 我知道;但这是原则,据我了解,这应该编译,但事实并非如此。
  • @Sam:不,真的不应该:)
  • 至少你在raptor 攻击中幸存下来!
  • @AthomSfere:尝试理解为什么某些代码无效是完全合理的。例如,goto自动生成 代码中很有用。 (async/await 有效地 生成一堆 goto。)
  • 很遗憾我们没有命名循环,那你可以去exit loop myOuterLoopName;

标签: c# visual-studio-2012 for-loop nested-loops goto


【解决方案1】:

标签本身并不存在:它标记了一个语句。来自 C# 5 规范的第 8.4 节:

标签语句允许语句以标签为前缀。块中允许带标签的语句,但不允许作为嵌入语句。

在这种情况下,您在方法的末尾应用标签 - 没有声明它是标签 for。所以编译器拒绝你的代码是绝对正确的。

如果你真的想要,你可以给一个多余的 return 语句添加一个标签:

exitMethod:
    return;
}

... 或者只是一个空的声明,正如 Irfan 所建议的那样。不过必须有一个声明。

但我不会推荐它。只需将任何 goto exitMethod; 语句更改为简单的 return

【讨论】:

    【解决方案2】:

    您可以放置​​空白语句。

    试试:

    exitMethod: ;            
    

    但无论如何,如果你真的想从当前方法返回,请使用 return 语句。 如果方法具有除 void 以外的其他返回类型,

    return (type);
    

    否则

    return;
    

    【讨论】:

      【解决方案3】:

      在这种情况下

      goto exitMethod;
      

      等同于普通

      return;
      

      并且该计划回报明显更具可读性。所以我不明白你为什么要这样做。

      【讨论】:

        【解决方案4】:
        "The goto statement transfers the program control directly to a labeled statement." 
        

        你有exitMethod 作为你的标签,但在你的第一个例子中你没有声明。这就是您收到错误的原因。

        goto reference

        【讨论】:

          【解决方案5】:

          您需要为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 标签。但是为什么。
          【解决方案6】:

          两件事,不建议先转到。由于标签的工作方式,它不允许您使用这样的标签。标签是源代码唯一标识符,允许您指向特定指令。在您尝试的情况下,它后面没有指令,因此它无法解析到指令的位置。这导致了您的错误。

          同样,您不应该以这种方式使用 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 是一个有用的临时更改。你的改变要困难得多。
          猜你喜欢
          • 1970-01-01
          • 2019-09-05
          • 2015-08-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-06
          • 1970-01-01
          相关资源
          最近更新 更多