Go To Statement Considered Harmful?

2019-04-18 14:19发布

If the statement above is correct, then why when I use reflector on .Net BCL I see it is used a lot?

EDIT: let me rephrase: are all the GO-TO's I see in reflector written by humans or compilers?

标签: c# .net goto bcl
15条回答
▲ chillily
2楼-- · 2019-04-18 14:52

The above isn't really correct - it was a polemical device used by Dijkstra at a time when gotos were about the only flow control structure in use. In fact, several people have produced rebuttals, including Knuth's classic "Structured Programming Using Goto" paper (title from memory). And there are some situations (error handling, state machines) where gotos can produce clearer code (IMHO), than the "structured" alternatives.

查看更多
姐就是有狂的资本
3楼-- · 2019-04-18 14:53

Keep in mind that the code you are seeing in Reflector is a disassembly -- Reflector is looking at the compiled byte codes and trying to piece together the original source code.

With that, you must remember that rules against gotos apply to high-level code. All the constructs that are used to replace gotos (for, while, break, switch etc) all compile down to code using JMPs.

So, Reflector looks at code much like this:

A:
    if !(a > b)
        goto B;
    DoStuff();
    goto A;
B:  ...

And must realize that it was actually coded as:

 while (a > b)
    DoStuff();

Sometimes the code being read to too complicated for it to recognize the pattern.

查看更多
来,给爷笑一个
4楼-- · 2019-04-18 14:54

If it's harmful or not, it's a matter of likes and dislikes of each one. I personally don't like them, and find them very unproductive as they attempt maintainability of the code.

Now, one thing is how gotos affect our reading of the code, while another is how the jitter performs when found one. From Eric Lippert's Blog, I'd like to quote:

We first run a pass to transform loops into gotos and labels.

So, in fact the compiler transforms pretty each flow control structure into goto/label pattern while emitting IL. When reflector reads the IL of the assembly, it recognizes the pattern, and transforms it back to the appropriate flow control structure.

In some cases, when the emitted code is too complicated for reflector to understand, it just shows you the C# code that uses labels and gotos, equivalent to the IL it's reading. This is the case for example when implementing IEnumerable<T> methods with yield return and yield break statements. Those kind of methods get transformed into their own classes implementing the IEnumerable<T> interface using an underlying state machine. I believe in BCL you'll find lots of this cases.

查看更多
登录 后发表回答