tags:

views:

660

answers:

13

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?

+11  A: 

These goto's are very often generated by the compiler, especially inside enumerators. The compiler always knows what she's doing.

If you find yourself in the need to use goto, you should make sure it is the only option. Most often you'll find there's a better solution.

Other than that, there are very few instances the use of goto can be justified, such as when using nested loops. Again, there are other options in this case still. You could break out the inner loop in a function and use a return statement instead. You need to look closely if the additional method call is really too costly.


In response to your edit:

No, not all gotos are compiler generated, but a lot of them result from compiler generated state machines (enumerators), switch case statements or optimized if else structures. There are only a few instances you'll be able to judge wether it was the compiler or the original developer. You can get a good hint by looking at the funtion/class name, a compiler will generate "forbidden" names to avoid name clashes with your code. If everything looks normal and the code has not been optimized or obfuscated the use of goto is probably intended.

Johannes Rudolph
The compiler always knows what **she's** doing. Something so finicky must be female.
Nifle
@Nifle: fixed. :-)
Johannes Rudolph
please see my edit
Yaron Naveh
+3  A: 

Go To statement itself is not harmful, it is even pretty useful sometimes. Harmful are users who tend to put it in inappropriate places in their code.

alemjerus
+12  A: 

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), then the "structured" alternatives.

anon
I agree, +1 for the scientifical perspective. An enumerator is a perfect example for a state machine.
Johannes Rudolph
It wasn't even a polemic device of Dijkstra's. As the wikipedia article points out he didn't choose the title for that paper. Ironic that he should be so famous for that title.
Eric Lippert
@Eric If something is published under your name, you are responsible for it - no-one else. And Dijkstra has a few other polemical goodies to his name.
anon
So @Neil, just to be clear, it is your position that if an editor changes the title of your article and publishes it without running it by you first, you're responsible, and no one else is responsible. Yes?
Eric Lippert
please see my edit
Yaron Naveh
+8  A: 

Obligatory XKCD

Neal Stephenson thinks it's cute to name his labels 'dengo'

tylerl
This happened to a guy in our office!
Dave
this almost happened to me D: ... i once had the thought to write a goto statement and i saw a shadow move near the door... and now i know what it was D:
Gabriel
+4  A: 

When compiled down to assembly code, all control structured and converted to (un)conditional jumps. However, the optimizer may be too powerful, and when the disassembler cannot identify what control structure a jump pattern corresponds to, the always-correct statement, i.e. goto label; will be emitted.

This has nothing to do with the harm(ful|less)ness of goto.

KennyTM
+8  A: 

I think the following excerpt from the Wikipedia Article on Goto is particularly relevant here:

Probably the most famous criticism of GOTO is a 1968 letter by Edsger Dijkstra called Go To Statement Considered Harmful. In that letter Dijkstra argued that unrestricted GOTO statements should be abolished from higher-level languages because they complicated the task of analyzing and verifying the correctness of programs (particularly those involving loops). An alternative viewpoint is presented in Donald Knuth's Structured Programming with go to Statements which analyzes many common programming tasks and finds that in some of them GOTO is the optimal language construct to use.

So, on the one hand we have Edsger Dijkstra (a incredibly talented computer scientist) arguing against the use of the GOTO statement, and specifically arguing against the excessive use of the GOTO statement on the grounds that it is a much less structured way of writing code.

On the other hand, we have Donald Knuth (another incredibly talented computer scientist) arguing that using GOTO, especially using it judiciously can actually be the "best" and most optimal construct for a given piece of program code.

Ultimately, IMHO, I believe both men are correct. Dijkstra is correct in that overuse of the GOTO statement certainly makes a piece of code less readable and less structured, and this is certainly true when viewing computer programming from a purely theoretical perspective.

However, Knuth is also correct as, in the "real world", where one must take a pragmatic approach, the GOTO statement when used wisely can indeed be the best choice of language construct to use.

CraigTP
FWIW, some of Knuth's proposed uses for `goto` have been subsumed by other constructs (like `break`) in more modern languages.
David Thornley
@David - Agreed. After all, it was 1974 when Donald Knuth published "Structured Programming With Goto Statements". His paper is as old as I am! :)
CraigTP
+1: This is the most balanced answer I've read in this thread, with the added virtue that it does not misrepresent what Dijkstra wrote.
Gorpik
+1  A: 

goto considered harmful (for human to use but for computers its okay).

because no matter how madly we(human) use goto, compiler always knows how to read the code.

Believe me...

Reading others code with gotos in it is HARD.
Reading your own code with gotos in it is HARDER.

That is why you see it used in low level (machine languages) and not in high level (human languages e.g. C#,Python...) ;)

TheMachineCharmer
+1  A: 

The general rule is that you don't need to use goto. As with any rule there are of course exceptions, but as with any exceptions they are few.

The goto command is like a drug. If it's used in limited amounts only in special situations, it's good. If you use too much all the time, it will ruin your life.

When you are looing at the code using Reflector, you are not seeing the actual code. You are seeing code that is recreated from what the compiler produced from the original code. When you see a goto in the recreated code, it's not certain that there was a goto in the original code. There might be a more structured command to control the flow, like a break or a continue which has been implemented by the compiler in the same way as a goto, so that Reflector can't tell the difference.

Guffa
+6  A: 

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.

James Curran
+1, the only real answer to this question.
Hans Passant
Right you are James, when you get down to the metal (or virtual metal in this case) it (flow control) is all just jumps (goto) with or without a condition.
Andre Artus
A: 

I sometimes use goto when I want to perform a termination action:

static void DoAction(params int[] args)
{
  foreach (int arg in args)
  {
    Console.WriteLine(arg);
    if (arg == 93) goto exit;
  }

  //edit:
  if (args.Length > 3) goto exit;
  //Do another gazillion actions you might wanna skip.

  //etc.
  //etc.

exit:
  Console.Write("Delete resource or whatever");
}

So instead of hitting return, I send it to the last line that performs another final action I can refer to from various places in the snippet instead of just terminating.

Shimmy
What's wrong with 'break'?
Gary Willoughby
I've edited my post
Shimmy
For this, I use `try .. finally`, and `return`.
Blorgbeard
Looks you didn't understand my snippet. What does a try help you here? you probably stopped on the "delete resource", but you forgot that it also says "whatever".
Shimmy
@Shimmy - I have looked at your example closely, and I fail to see why a `try{...}finally{...}` construct wouldn't be ideal for this situation, or why doing more than deleting a resource might be a factor. (Perhaps you are thinking of `using` which creates a `try{...}finally{...}` block and calls `Dispose()`?) Could you please provide more details on why a `goto` is better than a `finally` in this situation?
Jeffrey L Whitledge
Jeffrey, try/finlly would be equivalent, except when an exception is thrown. In the case above the the exit code will not run if an exception is thrown before it (this may be the desired behaviour, or a bug). You could replicate the exact flow of Shimmy's example without using a goto, but one needs to be careful that you don't write convoluted code just to avoid using goto. The reason to avoid goto is because it can turn your code into spaghetti, but I have seen programmers turn their code into spagbol just to avoid using goto. Optimize for legibility.
Andre Artus
A: 

"C provides the infinitely-abusable goto statement, and labels to branch to. Formally, the goto is never necessary, and in practice it is almost always easy to write code without it. We have not used goto in this book."

-- K&R (2nd Ed.) : Page 65

Gary Willoughby
A: 

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.

Fede
+1  A: 

In decompiled code, virtually all gotos that you see will be synthetic. Don't worry about them; they're an artifact of how the code is represented at the low level.

As to valid reasons for putting them in your own code? The main one I can think of is where the language you are using does not provide a control construct suitable for the problem you are tackling; languages which make it easy to make custom control flow systems typically don't have goto at all. It's also always possible to avoid using them at all, but rearranging arbitrarily complex code into a while loop and lots of conditionals with a whole battery of control variables... that can actually make the code even more obscure (and slower too; compilers usually aren't smart enough to pick apart such complexity). The main goal of programming should be to produce a description of a program that is both clear to the computer and to the people reading it.

Donal Fellows
You mean that the real source code does not contain goto, just the decompiled code?
Yaron Naveh
@Yaron: He means that the decompiled code will likely contain gotos, whether the original source had it or not. All the flow control structures are ultimately constructed from jumps (gotos) when you dig down deep enough. You are likely to see it in decompiled code when the decompiler cannot infer the original control structure, or when the flow control structure is just cleaner way of using goto (e.g. switch/case, break, continue) anyway.
Andre Artus
@Andre: Right. @Yaron: Decompilers can't handle every way of using every control construct; they're deliberately not the smartest tool ever, because that makes them more likely to go wrong, and fundamental correctness is better than being able to make some situations prettier. Decompilation was always only ever a poor second to *actually having the source*.
Donal Fellows