有人还在C#中使用[goto]吗?如果是,为什么
本文关键字:如果 为什么 goto | 更新日期: 2023-09-27 18:00:55
我想知道是否还有人在C#中使用"goto"关键字语法,以及这样做的可能原因。
我倾向于将任何导致读者跳过代码的语句视为不良做法,但我想知道是否有任何可信的场景可以使用这种语法?
转到关键字定义
在某些(罕见的(情况下,goto实际上可以提高可读性。事实上,您链接到的文档列出了两个示例:
goto的一个常见用途是将控制权转移到特定的switchcase标签或switch语句中的默认标签。
goto语句对于摆脱深度嵌套的循环也很有用。
下面是后一个例子:
for (...) {
for (...) {
...
if (something)
goto end_of_loop;
}
}
end_of_loop:
当然,还有其他方法可以解决这个问题,比如将代码重构为函数,在其周围使用伪块等等(有关详细信息,请参阅此问题(。附带说明一下,Java语言设计人员决定完全禁止goto,并引入标记的break语句。
我记得这个部分
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;
}
请参阅本
我在Eduasync中广泛使用它,以显示编译器在C#5中使用异步方法时为您生成的代码类型。你会在迭代器块中看到同样的东西。
不过,在"正常"代码中,我不记得上次使用它是什么时候了…
编译器在生成的各种代码中使用goto
语句,例如在生成的迭代器块类型中(在使用yield return
关键字时生成-我很确定生成的XML串行化类型中也有一些goto
语句。
请参阅Iterator块实现详细信息:自动生成的状态机,了解C#编译器为什么/如何处理这一问题的更多详细信息。
除了生成的代码之外,在普通代码中使用goto
语句并不是一个很好的理由——这会使代码更难理解,因此更容易出错。另一方面,像这样在生成的代码中使用goto
语句可以简化生成过程,而且通常情况下是可以的,因为没有人会读取(或修改(生成的代码,也不会因为机器在写而出错。
关于反对goto
的论点,请参阅Go to语句,以及一段经典的编程历史。
我不记得曾经使用过goto
。但是也许它改善了一个永远不想退出的循环的意图(没有break
,但你仍然可以return
或throw
(:
forever: {
// ...
goto forever;
}
再说一遍,一个简单的while (true)
就足够了。。。
此外,在希望循环的第一次迭代从循环中间开始的情况下,可以使用:请查看此处的示例。
goto非常适合在break无法正常工作的情况下(比如在错误条件下(中断许多循环,正如Kragen所说,编译器使用goto来生成switch语句和其他一些东西。
处理器至少实现了一条跳转指令,我相信很多语句在实现或解释中都使用了这些指令。
使用第三代或第四代语言的好处之一是,这些物理细节被抽象掉了。虽然我们应该注意泄漏抽象的规律,但我认为我们也应该按照预期使用我们的工具(对不起(。如果我正在编写代码,并且goto
似乎是个好主意,那么是时候进行重构了。结构化语言的目的是避免这些"跳跃",并在我们的工程中创建一个逻辑流。
我应该避免使用break
,但我不能忽视性能优势。然而,如果我有相互需要break
的嵌套循环,那么是时候重构了。
如果有人能提出使用goto
,这似乎比重构更好,我会很乐意撤回我的答案。
我希望我不会因为冲到这里的"自行车棚"而感到内疚。就像Kragen说的,对Dijkstra来说足够好的东西对我来说也足够好
Goto再好不过了。继续、断开(开关/情况除外(、(多次(回球和投掷也应保持在最低限度。你永远不想从巢环的中间逃脱。您总是希望循环控制语句具有所有的循环控制。缩进包含信息,所有这些语句都会丢弃这些信息。你不妨去掉所有的缩进。