127

I was wondering whether anyone still uses the "goto" keyword syntax in C# and what possible reasons there are for doing so.

I tend to view any statements that cause the reader to jump around the code as bad practice but wondered whether there were any credible scenarios for using such a syntax?

Goto Keyword Definition

skaffman
  • 398,947
  • 96
  • 818
  • 769
Brian Scott
  • 9,221
  • 6
  • 47
  • 68
  • 1
    When you _do_ need to use it, you've probably painted yourself into corner. – Grant Thomas Jul 01 '11 at 09:05
  • Possibly related question, http://stackoverflow.com/questions/2542289/is-there-ever-a-reason-to-use-goto-in-modern-net-code –  Jul 01 '11 at 09:07
  • 5
    what do you mean "still"? Was there a period of time people used it all the time [in c#]? – Massif Jul 01 '11 at 10:22
  • 6
    @Massif: "still" was intended to emphasise the modern opinion of the use of "goto" as a prelude to spaghetti code and a lack of readbility in source code. Very rarely do you see any code examples including this particular keyword which was why I was interested in asking in the first place. – Brian Scott Jul 01 '11 at 12:36
  • 65
    If the reader "jumping around" the code is bad practice then do you also avoid "break", "continue", "throw", and "return"? They all cause a branch in control flow, sometimes a non-local branch. "Throw" doesn't even tell you where it is going, unlike goto. – Eric Lippert Jul 01 '11 at 13:57
  • 2
    I use `goto` to break a loop and go back to starting statement according to specific condition – Nitin Sawant Oct 09 '13 at 09:19
  • We're allowed to use `break` to for-loop around a list looking for something and then break out when it's found (made redundant by linq now), `throw` in special circumstances (business logic exception, you should validate first and there is only ever one place where it could go and that's the entry point `catch` handler for the Dll you're in) and you're only allowed one `return` and it's the last line of the method. Never heard of `continue` @EricLippert – RoboJ1M Nov 21 '13 at 17:35
  • 4
    I like goto. I tried avoiding it because of the trend of people saying to avoid it because it makes code harder to read. Having learned Assembly language and branch statements, I think sometimes there are times, it may make the code more readable. I do think multiple uses in one method and jumping too far down in the code can do more harm than good. But if you are thinking a goto would work nicely here, a simple goto once in a while should not have you going out of your way to avoid just because the common consensus is to avoid it. – eaglei22 Feb 05 '18 at 16:35

8 Answers8

115

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.

Community
  • 1
  • 1
Heinzi
  • 167,459
  • 57
  • 363
  • 519
  • 59
    Normally I'd *try* to refactor this to put the loops in a separate method which I could just return from... – Jon Skeet Jul 01 '11 at 09:00
  • 3
    @Heinzi - I have not seen goto being warranted. Like Jon says, if it is being "warranted", the code is begging to be refactored. – manojlds Jul 01 '11 at 09:01
  • I dunno about C#, but java gives you `break – mihsathe Jul 01 '11 at 09:01
  • 34
    labeled break, just a longer way of saying goto because it does the same freakin thing.... – Jesus Ramos Jul 01 '11 at 09:02
  • 24
    @Jesus but then with goto, you can go anywhere. Labeled break ensures you are going just outside the loop. – mihsathe Jul 01 '11 at 09:03
  • 1
    Unless you're being adventurous and using goto with an address (i've seen it done before) then that problem is mitigated. And I doubt someone is using detour hooks in your C# and Java code to exploit goto statements. – Jesus Ramos Jul 01 '11 at 09:05
85

I remember this part

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

To something like this

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

Refer This

Stephen Holt
  • 2,360
  • 4
  • 26
  • 34
V4Vendetta
  • 37,194
  • 9
  • 78
  • 82
  • 22
    I actually see this as the most valid reason to use [goto] yet. At least in this scenario it increases readability for programmers unaware that cases drop into each other without a break statement. – Brian Scott Jul 01 '11 at 09:44
  • 12
    @Brian Scott, V4Vendetta. Unless I'm mistaken the first statement doesn't compile in C#. That would aid the programmer's understanding. – Jodrell Jul 01 '11 at 09:56
  • 3
    V4Vendetta why did you insert a break on the first code snippet...? It was better to show it without the break, otherwise the two snippets do different things. The reason why you need the goto in the second example is precisely because the first one doesn't compile in C# (as it would in C). – Stephen Holt Oct 20 '15 at 13:32
  • @BrianScott even in languages which support this drop-through, like C++, there may be possibility that the author just forgot to write a break. So I usually write a comment, that it was intended. Having a special language construct for this is better. – Alex Che Mar 21 '23 at 15:40
27

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...

Curtis
  • 37
  • 9
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    can you provide a small example of why this approach was preferred or was it simply a personal preference? – Brian Scott Jul 01 '11 at 09:04
  • 2
    @Brian: It's not really clear what you mean. Eduasync shows the equivalent C# code to what the compiler does for you - and it generates code which uses goto, effectively... – Jon Skeet Jul 01 '11 at 09:43
  • I am using a de-compiler to inspect what is going on inside an application and it revealed goto statements in a couple of places. For that reason I googled the cause of it and sure enough, probably the reason is it was compiled then decompiled, and the process has done this to me – Kyle Burkett Oct 06 '22 at 21:19
12

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.

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 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.

See Go-to statement considered harmful for an argument against goto as well as a classic piece of programming history.

Justin
  • 84,773
  • 49
  • 224
  • 367
  • 7
    This is stupid: there are several cases were goto is useful, as illustrated by other answers. Either you rubut them explicitly, or just saying "it is wrong" is, well, wrong. – o0'. Sep 04 '13 at 14:29
  • 1
    @Lohoris I'm not buying it - every example I've seen where goto "improves readability" (including the answers here) would be **far** more readable after some simple refactoring. – Justin Sep 04 '13 at 16:04
  • 4
    @Justin no, sometimes nested loops are just the most natural way of doing something, for instance if you are traversing an array of arrays. – o0'. Sep 04 '13 at 17:30
  • @Lohoris Often the natural way of coding something is just the way that the programmer is most familiar with - "natural" doesn't always correlate with "readable". What is wrong with a simple `return` for breaking out of nested loops? Although [Purists](http://en.wikipedia.org/wiki/Liskov_substitution_principle) would still disagree with this, that's not necessarily a view that I subscribe to. – Justin Sep 04 '13 at 17:46
  • @Justin you need it to be a function to have `return`. – o0'. Sep 04 '13 at 17:48
  • @Lohoris Then refactor it into a function – Justin Sep 05 '13 at 08:50
  • 8
    @Justin it's not always clearer to have it into a function. You're forcing something (having a function) just to avoid something you hate religiously (using a goto). Clear indication of doing something wrong. – o0'. Sep 05 '13 at 09:01
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/36840/discussion-between-justin-and-lohoris) – Justin Sep 05 '13 at 09:05
  • 5
    @Justin Functions calls have overhead. `goto` does not. Something to consider. – Dan Bechard Mar 02 '16 at 22:20
  • The [C#] compiler 'using [goto] IL internally' is irrelevant to supporting `goto` in the C# language. It may be relevant to X-*transpiled*-to-C# code, but that's a different situation. The inverse is probably more useful: having `goto` in C# allows IL *de-compilers* 'an easy way' to get back to C#. – user2864740 Sep 22 '18 at 04:17
11

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.

Community
  • 1
  • 1
Jordão
  • 55,340
  • 13
  • 112
  • 144
9

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.

Jesus Ramos
  • 22,940
  • 10
  • 58
  • 88
3

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.

Community
  • 1
  • 1
Jodrell
  • 34,946
  • 5
  • 87
  • 124
  • 1
    Taking a `dynamic` object and walking it's object graph that contains multiple dictionaries to get down to the values I need. Doesn't make sense to use methods that have a parameter of `dynamic` yet expect an exact object shape. With goto to break out multiple layers and continue walking through a collection of these objects. [I don't own the types so I can't provide better access, so reflection or dynamic it is] – Chris Marisic Aug 20 '14 at 21:21
-7

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.

  • 12
    You would want to break out of a loop if there is no point in keeping the execution of the loop. Otherwise you'll end up wasting more processing time in longer loops for no reason. – Stephen Jan 03 '12 at 17:04
  • 16
    @Kirk, this sounds like an opinion rather than anything quantitive? – Brian Scott Jan 04 '12 at 08:42