There are some (rare) cases where goto can actually improve readability. In fact, the documentation you linked to lists two examples:
A common use of goto is to transfer control to a specific switch-case label or the default label in a switch statement.
The goto statement is also useful to get out of deeply nested loops.
Here's an example for the latter one:
for (...) {
for (...) {
...
if (something)
goto end_of_loop;
}
}
end_of_loop:
Of course, there are other ways around this problem as well, such as refactoring the code into a function, using a dummy block around it, etc. (see this question for details). As a side note, the Java language designers decided to ban goto completely and introduce a labeled break statement instead.
I use it extensively in Eduasync to show the kind of code that the compiler generates for you when using async methods in C# 5. You'd see the same thing in iterator blocks.
In "normal" code though, I can't remember the last time I used it...
The compiler uses goto statements in various pieces of generated code, for example in generated iterator block types (generated when using the yield return keyword - I'm pretty sure that the generated XML serialisation types also have a few goto statements in there somewhere too.
Other than generated code there isn't a good reason to use a goto statement in normal code - it makes the code harder to understand and as a result more error-prone. On the other hand using goto statements in generated code like this can simplify the generation process and is normally fine because nobody is going to read (or modify) the generated code and there is no chance of mistakes being made because a machine is doing the writing.
I don't remember ever using goto. But maybe it improves the intent of a forever loop that you really never want to exit (no break, but you can still return or throw):
forever: {
// ...
goto forever;
}
Then again, a simple while (true) should suffice...
Also, you could use in a situation where you want the first iteration of a loop to start in the middle of the loop: look here for an example.
goto is great for breaking out of many loops where break would not work well (say upon error conditions), and as Kragen said goto is used by the compiler to generate switch statements and some other things as well.
The processor implements at least one jump instruction and I'm sure lots of statements use those in thier implementation or interpretation.
One of the good things about using a 3rd or 4th generation langauge is that these physical details are abstracted away from us. Whilst we should be mindful of the law of leaky abstraction I think that we should also use our tools as they are intended (sorry). If I were writing code and a goto seemed like a good idea, it would be time to refactor. The purpose of a structured language is to avoid these "jumps" and to create a logical flow in our engineering.
I should avoid the use of break but I can't overlook the performance benefit. However, if I have nested loops that mutually need to break it is time to refactor.
If anybody can propose a use of goto that seems better than refactoring I will gladly withdraw my answer.
I hope I'm not guilty of rushing to the "bike shed" here. Like Kragen says, whats good enough for Dijkstra is good enough for me.
Goto is never better. And continue, break (except in switch/case), (multiple) return, and throw should also be kept to the barest minimum. You never want to escape from the middle of nest loops. You always want the loop control statements have all the loop control. Indenting has information, and all these statement throw that information away. You might as well take out all the indenting.
发布评论
评论(8)
在某些(罕见)情况下,goto 实际上可以提高可读性。事实上,您链接到的文档列出了两个示例:
下面是后一个问题的示例:
当然,还有其他方法可以解决这个问题,例如将代码重构为函数、在其周围使用虚拟块等(请参阅 此问题了解详细信息)。附带说明一下,Java 语言设计者决定完全禁止 goto 并引入带标签的 break 语句。
There are some (rare) cases where goto can actually improve readability. In fact, the documentation you linked to lists two examples:
Here's an example for the latter one:
Of course, there are other ways around this problem as well, such as refactoring the code into a function, using a dummy block around it, etc. (see this question for details). As a side note, the Java language designers decided to ban goto completely and introduce a labeled break statement instead.
我记得这部分
类似的内容
请参阅 这个
I remember this part
To something like this
Refer This
我在 Eduasync 中广泛使用它来显示编译器在使用异步方法时为您生成的代码类型C# 5。您会在迭代器块中看到同样的事情。
但在“正常”代码中,我不记得上次使用它是什么时候......
I use it extensively in Eduasync to show the kind of code that the compiler generates for you when using async methods in C# 5. You'd see the same thing in iterator blocks.
In "normal" code though, I can't remember the last time I used it...
编译器在生成的代码的各个部分中使用
goto
语句,例如在生成的迭代器块类型中(使用yield return
关键字时生成 - 我非常确定生成的XML 序列化类型也有一些goto
语句,请参阅 迭代器块实现细节:自动生成的状态机 了解有关 C# 编译器为何/如何处理此问题的更多详细信息
除了生成的代码之外,没有充分的理由使用
goto 语句 - 它使代码更难理解,因此更容易出错;另一方面,在生成的代码中使用
goto
语句可以简化生成过程。过程并且通常很好,因为没有人会阅读(或修改)生成的代码,并且不会因为机器正在编写而出现错误。请参阅被视为有害的转到声明,了解反对
goto
以及编程史上的经典片段。The compiler uses
goto
statements in various pieces of generated code, for example in generated iterator block types (generated when using theyield return
keyword - I'm pretty sure that the generated XML serialisation types also have a fewgoto
statements in there somewhere too.See Iterator block implementation details: auto-generated state machines for some more details on why / how the C# compiler handles this.
Other than generated code there isn't a good reason to use a
goto
statement in normal code - it makes the code harder to understand and as a result more error-prone. On the other hand usinggoto
statements in generated code like this can simplify the generation process and is normally fine because nobody is going to read (or modify) the generated code and there is no chance of mistakes being made because a machine is doing the writing.See Go-to statement considered harmful for an argument against
goto
as well as a classic piece of programming history.我不记得曾经使用过
goto
。但是也许它改善了永远不想退出的永远循环的意图(没有break
,但你仍然可以return
或throw
):话又说回来,一个简单的
while (true)
就足够了...此外,您可以在需要第一次迭代的情况下使用从循环中间开始的循环:look 此处为例。
I don't remember ever using
goto
. But maybe it improves the intent of a forever loop that you really never want to exit (nobreak
, but you can stillreturn
orthrow
):Then again, a simple
while (true)
should suffice...Also, you could use in a situation where you want the first iteration of a loop to start in the middle of the loop: look here for an example.
goto 非常适合打破许多 Break 不能很好地工作的循环(比如在错误条件下),并且正如 Kragen 所说,编译器使用 goto 来生成 switch 语句和其他一些东西。
goto is great for breaking out of many loops where break would not work well (say upon error conditions), and as Kragen said goto is used by the compiler to generate switch statements and some other things as well.
处理器至少实现一个跳转指令并且我确信有很多语句在其实现或解释中使用它们。
使用 3rd 或 第四代 语言是这些物理细节从我们身上抽象出来。虽然我们应该注意泄漏抽象定律,但我认为我们也应该使用我们的工具的用途 (抱歉)。如果我正在编写代码并且
goto
似乎是个好主意,那么就该重构了。结构化语言的目的是避免这些“跳跃”并在我们的工程中创建逻辑流程。我应该避免使用
break
但我不能忽视性能优势。但是,如果我有相互需要中断
的嵌套循环,那么就该重构了。如果有人可以建议使用似乎比重构更好的 goto,我会很乐意撤回我的答案。
我希望我没有因为冲向“自行车棚而感到内疚“ 这里。就像 Kragen 所说,对 Dijkstra 来说足够好的对我来说就足够了。
The processor implements at least one jump instruction and I'm sure lots of statements use those in thier implementation or interpretation.
One of the good things about using a 3rd or 4th generation langauge is that these physical details are abstracted away from us. Whilst we should be mindful of the law of leaky abstraction I think that we should also use our tools as they are intended (sorry). If I were writing code and a
goto
seemed like a good idea, it would be time to refactor. The purpose of a structured language is to avoid these "jumps" and to create a logical flow in our engineering.I should avoid the use of
break
but I can't overlook the performance benefit. However, if I have nested loops that mutually need tobreak
it is time to refactor.If anybody can propose a use of
goto
that seems better than refactoring I will gladly withdraw my answer.I hope I'm not guilty of rushing to the "bike shed" here. Like Kragen says, whats good enough for Dijkstra is good enough for me.
后藤再好不过了。 continue、break(除 switch/case 外)、(多次)return 和 throw 也应保持在最低限度。你永远不想逃离嵌套循环的中间。您总是希望循环控制语句拥有所有循环控制权。缩进包含信息,而所有这些语句都会丢弃该信息。您不妨删除所有缩进。
Goto is never better. And continue, break (except in switch/case), (multiple) return, and throw should also be kept to the barest minimum. You never want to escape from the middle of nest loops. You always want the loop control statements have all the loop control. Indenting has information, and all these statement throw that information away. You might as well take out all the indenting.