有人还在C#中使用[goto]吗?为什么?[关闭]


104

我想知道是否有人在C#中仍使用“ goto”关键字语法,以及这样做的可能原因是什么?

我倾向于将任何导致读者无视代码的语句视为不良做法,但想知道是否存在使用这种语法的可靠方案?

转到关键字定义


3
你是什​​么意思 人们是否一直在[c#]中一直使用它?
Massif'7

4
@Massif:“ still”旨在强调使用“ goto”作为通心粉代码的前奏以及源代码缺乏可读性的现代观点。您很少看到任何包含此特定关键字的代码示例,这就是为什么我首先有兴趣询问的原因。
Brian Scott

50
如果读者“跳来跳去”该代码是错误的做法,那么您还避免“中断”,“继续”,“投掷”和“返回”吗?它们全都在控制流中引起分支,有时是非本地分支。与goto不同,“ throw”甚至不告诉您它的去向。
埃里克·利珀特

2
我习惯goto打破循环,然后根据特定条件返回开始声明
Nitin Sawant 2013年

3
我喜欢goto。我之所以尝试避免使用它,是因为人们倾向于避免使用它,因为这样会使代码难以阅读。学习了汇编语言和分支语句后,我认为有时有时,这可能会使代码更具可读性。我确实认为,在一种方法中多次使用并且代码中跳得太远可能弊大于利。但是,如果您认为goto在这里可以很好地工作,那么不时地进行一次简单的goto转换,就不会因为唯一的共识就是避免这种情况。
eaglei22 '18

Answers:


93

在某些(很少)情况下,goto可以真正提高可读性。实际上,您链接到的文档列出了两个示例:

goto的常见用法是将控制权转移到特定的切换用例标签或switch语句中的默认标签。

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

这是后一个示例:

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

end_of_loop:

当然,还有其他方法可以解决此问题,例如将代码重构为函数,在其周围使用伪块等(有关详细信息,请参见此问题)。作为附带说明,Java语言设计人员决定完全禁止goto并引入带标签的break语句。


47
通常,我会尝试将其重构为将循环放到一个单独的方法中,然后我可以从该方法中返回...
Jon Skeet

2
@Heinzi-我还没有看到goto的必要性。就像乔恩(Jon)所说的那样,如果要“保证”代码,就恳求对其进行重构。
manojlds 2011年

29
标记符,只是一种说法转到因为它同样刻着的事情更长的路......
耶稣拉莫斯

20
@耶稣,但是有了goto,您可以去任何地方。标记的中断可确保您走出循环。
mihsathe 2011年

1
除非您喜欢冒险并且在地址上使用goto(我以前见过),否则该问题将得到缓解。而且我怀疑有人在您的C#和Java代码中使用弯路挂钩来利用goto语句。
耶稣拉莫斯

65

我记得这部分

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

对于这样的事情

switch (a)     
{
    case 3: 
        b = 7;
        goto case 4;    
    case 4: 
        c = 3;
        break;     
    default: 
        b = 2;
        c = 4;
        break;
}

推荐这个


17
实际上,这是使用[goto]的最有效理由。至少在这种情况下,它提高了程序员的可读性,而程序员无需意识到情况之间会发生断言而没有break语句。
Brian Scott

11
@Brian Scott,V4仇杀队。除非我没有记错,否则第一条语句不会在C#中编译。这将有助于程序员的理解。
Jodrell

2
V4Vendetta为什么在第一个代码段中插入一个中断点...?最好不间断地显示它,否则这两个片段会做不同的事情。在第二个示例中需要goto的原因恰好是因为第一个示例没有在C#中进行编译(就像在C中那样)。
Stephen Holt 2015年

23

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

在“普通”代码中,我不记得上次使用它了。


1
您能否提供一个小例子说明为什么首选此方法,或者仅仅是个人喜好?
Brian Scott

1
@Brian:不清楚你的意思。Eduasync显示与编译器为您所做的等效的C#代码-并且它生成有效地使用goto的代码...
Jon Skeet

9

goto非常适合打破很多循环,在这些循环中,break不能很好地工作(例如在错误情况下),正如Kragen所说,goto被编译器用来生成switch语句和其他一些东西。


7
当然,“中断” /“继续”是更好的循环管理方法,而不是要求代码编辑器跳开源代码以试图了解下一步发生在哪里?
Brian Scott

6
如果您有嵌套循环,则不会。
耶稣拉莫斯

1
好的,我可以将其视为有效方案。
Brian Scott

1
在错误情况下,您应该考虑引发异常。
Jodrell

6
如果要在内部毫无例外地处理错误,这将是一种有效的方法。
耶稣拉莫斯

8

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

forever: {
  // ...
  goto forever;
}

再说一次,一个简单的while (true)就足够了...

同样,您可以在希望循环的第一次迭代在循环的中间开始的情况下使用:在此处查看示例。


链接的答案包含一个“有趣”的使用goto..和while(true) {..}是不是一个有趣的使用..
user2864740

5

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

有关C#编译器为何/如何处理此问题的更多详细信息,请参见迭代器块实现细节:自动生成的状态机

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

请参阅Go-to语句,它被视为有害的论点goto以及一段经典的编程历史。


4
这很愚蠢:如其他答案所示,有几种情况下goto是有用的。您要么明确地批评他们,要么只是说“这是错误的”,那是错误的。
o0'。

@Lohoris我不买它-我看到的每个示例在经过一些简单的重构后,goto“提高可读性”(包括此处的答案)的可读性就会大大提高。
贾斯汀

3
@Justin不,有时嵌套循环只是做某事的最自然的方法,例如,如果您遍历数组数组。
o0'。

6
@Justin将其集成到函数中并不总是那么清晰。您在强迫某事(具有某个功能)只是为了避免您虔诚地讨厌某事(使用goto)。明确指示做错了事。
o0'。

3
@Justin函数调用会产生开销。goto才不是。需要考虑的事情。
Dan Bechard

2

处理器至少执行一条跳转指令,而且我敢肯定,很多语句会在其实现或解释中使用这些指令

使用第3第4代语言的好处之一是,这些物理细节是从我们这里抽象出来的。尽管我们应该注意泄漏抽象定律,但我认为我们也应该按预期使用我们的工具对不起)。如果我正在编写代码并且goto似乎是个好主意,那么该是重构的时候了。结构化语言的目的是避免这些“跳跃”并在我们的工程中创建逻辑流程。

我应该避免使用,break但不能忽视其性能优势。但是,如果我有相互需要的嵌套循环,break那就该重构了。

如果有人可以提议使用goto它似乎比重构更好,那么我很乐意撤回我的回答。

我希望我对赶赴这里的“ 自行车棚 ” 不感到内。就像Kragen所说的那样,对Dijkstra来说足够好对我来说也足够好。


1
dynamic拿一个对象并走它的对象图,其中包含多个字典以求出所需的值。使用参数为,dynamic但期望对象形状精确的方法没有意义。使用goto可以突破多层并继续遍历这些对象的集合。[我不拥有这些类型,所以我无法提供更好的访问权限,因此它具有反射性或动态性]
Chris Marisic 2014年

-6

后藤再好不过了。并继续,中断(在切换/情况下除外),(多次)返回和投掷也应保持在最低水平。您永远都不想从嵌套循环的中间逃脱。您始终希望循环控制语句具有所有循环控制。缩进具有信息,所有这些语句都会丢弃该信息。您不妨删除所有缩进。


10
如果没有必要保持循环的执行,那么您可能想跳出循环。否则,您将无缘无故地在更长的循环中浪费更多的处理时间。
Skuld 2012年

12
@Kirk,这听起来像是一种意见,而不是定量的?
Brian Scott
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.