有人还在C#中使用[goto],如果是这样,为什么?

Bri*_*ott 96 .net c# coding-style goto

我想知道是否还有人在C#中使用"goto"关键字语法,以及可能的原因.

我倾向于查看任何导致读者跳过代码作为不良做法的陈述,但想知道是否有任何可信的场景使用这样的语法?

转到关键字定义

Hei*_*nzi 87

有一些(罕见的)goto实际上可以提高可读性的情况.实际上,您链接的文档列出了两个示例:

goto的一个常见用途是将控制转移到特定的switch-case标签或switch语句中的默认标签.

goto语句对于摆脱深层嵌套循环也很有用.

以下是后者的示例:

for (...) {
    for (...) {
        ...
        if (something)
            goto end_of_loop;
    }
}

end_of_loop:
Run Code Online (Sandbox Code Playgroud)

当然,还有其他方法可以解决这个问题,例如将代码重构为函数,在其周围使用虚拟块等等(有关详细信息,请参阅此问题).作为旁注,Java语言设计者决定完全禁止goto并引入带标签的break语句.

  • 通常我会尝试*重构这个以将循环放在一个单独的方法中,我可以从...返回 (44认同)
  • 标记为休息,只是更长的说goto的方式,因为它做同样的怪事.... (29认同)
  • @Jesus然后用goto,你可以去任何地方.标记的断点确保您在循环之外. (20认同)
  • @Heinzi - 我没有看到goto被保证.就像Jon说的那样,如果它是"有保证的",代码就是要求重构. (2认同)

V4V*_*tta 63

我记得这部分

switch (a)     
{ 
    case 3: 
        b = 7;
        // We want to drop through into case 4, but C# doesn't let us
    case 4: 
        c = 3;
        break; 
    default: 
        b = 2;
        c = 4;
        break; 
}
Run Code Online (Sandbox Code Playgroud)

对于这样的事情

switch (a)     
{
    case 3: 
        b = 7;
        goto case 4;    
    case 4: 
        c = 3;
        break;     
    default: 
        b = 2;
        c = 4;
        break;
}
Run Code Online (Sandbox Code Playgroud)

请参阅

  • 我实际上认为这是使用[goto]的最有效理由.至少在这种情况下,它增加了程序员的可读性,使他们不知道案例在没有break语句的情况下互相落入. (16认同)
  • @Brian Scott,V4Vendetta.除非我弄错了,否则第一个语句不会在C#中编译.这将有助于程序员的理解. (11认同)
  • V4Vendetta 为什么你在第一个代码片段上插入一个中断......?最好不中断地展示它,否则两个片段会做不同的事情。在第二个示例中需要 goto 的原因正是因为第一个不在 C# 中编译(就像在 C 中一样)。 (2认同)

Jon*_*eet 22

我在Eduasync中广泛使用它来显示编译器在C#5中使用异步方法时为您生成的代码类型.您将在迭代器块中看到相同的内容.

但是在"普通"代码中,我记不清上次使用它了...

  • @Brian:你的意思不是很清楚。Eduasync 显示了与编译器为您所做的等效的 C# 代码 - 它生成的代码有效地使用了 goto... (2认同)

Jes*_*mos 8

goto非常适合打破许多循环,其中break不能很好地工作(比如错误条件),并且正如Kragen所说,编译器使用goto来生成switch语句和其他一些东西.

  • 肯定"中断"/"继续"是更好的循环管理方法,而不是要求代码编辑器跳转源代码试图了解下一步发生的位置? (7认同)
  • 如果您有嵌套循环,则不会. (6认同)
  • 如果你想在没有异常的情况下在内部处理错误,这将是一种有效的方法. (6认同)

Jus*_*tin 6

编译器goto在各种生成的代码中使用语句,例如在生成的迭代器块类型中(使用yield return关键字时生成)- 我很确定生成的XML序列化类型goto在某处也有一些语句.

请参阅Iterator块实现详细信息:自动生成的状态机,以获取有关C#编译器处理此问题的原因/方式的更多详细信息.

除了生成的代码之外,没有充分的理由goto在普通代码中使用语句 - 它使代码更难理解,因此更容易出错.另一方面,goto在生成的代码中使用这样的语句可以简化生成过程并且通常很好,因为没有人会读取(或修改)生成的代码,并且由于机器正在进行编写而不会出错.

请参阅认为对参数有害的Go-to语句goto以及经典的编程历史记录.

  • @Justin将它变成一个函数并不总是更清楚.你强迫某事(有一个功能)只是为了避免你讨厌的东西(使用goto).做错事的明确迹象. (8认同)
  • 这是愚蠢的:有几个案例是goto很有用,如其他答案所示.要么你明确地说它们,要么只是说"它是错的"是错的. (5认同)
  • @Justin 不,有时嵌套循环只是做某事最自然的方式,例如,如果您正在遍历数组数组。 (4认同)
  • @Justin 函数调用有开销。`goto` 没有。需要考虑的事情。 (4认同)

Jor*_*dão 6

我不记得曾经使用过goto.但也许它改善了你永远不想退出的永久循环的意图(不break,但你仍然return可以throw):

forever: {
  // ...
  goto forever;
}
Run Code Online (Sandbox Code Playgroud)

再说一次,简单while (true)应该就够了......

此外,您可以在需要循环的第一次迭代在循环中间开始的情况下使用:在此处查看示例.