1

I have read multiple articles saying using goto is a massive no no in programming. But some specifically indicate that it's the abuse of goto that is wrong and that in some cases, like switch cases, it's the intended use.

So my question to you is, for future reference, which is best practice/more efficient.

this:

switch (a)
{
    case 1:
        //Something specific for case 1
        break;
    case 2:
        //Something specific to default and case 2
        break;
    default:
        //Something specific for default
        goto case 2;
}

or this:

switch (a)
{
    case 1:
        //Something specific for case 1
        break;
    case 2:
        //Something specific to default and case 2
        thatFunction();
        break;
    default:
        //Something specific for default
        thatFunction();
        break;
}

void thatFunction() { /*Case 2 stuff*/ }

EDIT: These two switch statements are examples, the actual code contains many more cases.

Everyone at my workplace has either never used goto or say they've only heard to never ever use it. So I came here for a definitive answer. I'm looking for an answer and an explanation or links to one. Thanks,

Alox
  • 651
  • 12
  • 24

2 Answers2

3

You always need to understand the reasoning behind any "no-no" (or "yes-yes"). That way you can understand where it makes sense to apply the rule, and where it doesn't.

The big fight against goto goes all the way back to programming without true procedures and functions, or even something as simple as a loop. goto allowed you to jump from anywhere to anywhere else, and it was extremely hard to think about what it actually means. "Don't use goto" was part of the movement to structured code, as opposed to lots of jumps all the way around the code; using things like for (int i = 10; i > 0; i--) { ... } for iteration, rather than if (i-- > 0) goto startLoop;.

In a switch, goto is constrained - it can only do one thing, execute a branch of the switch statement. In fact, in C#, even outside of a switch statement, goto is very constrained and safe, and rarely has any of the implications that were assumed when the "Goto is evil" movement started. That doesn't mean you should start replacing all your loops with gotos, of course :)

Now, if things are getting this complicated, it might be that a switch isn't a good solution for your problem in the first place. Perhaps you can use a different structure to do what you're trying to do - there's many ways to do polymorphism and/or code reuse in C#, and one of those might be a better approach that will allow you to use clearer code to do what you're trying to do. But we can't really help you with that :)

Luaan
  • 62,244
  • 7
  • 97
  • 116
  • Despite the safeness inside switch statements I still give `goto` a wary look. I'm more likely to find an alternative, such as using `bool breakEarly` inside nested loops rather than use `goto breakOutOfInnerLoop`. It feels safer and more readable. Switch statements for fall-through only because the Thing I Want To Do Which Works In Another Language is only possible with a `goto`. – Draco18s no longer trusts SE Apr 20 '17 at 16:03
  • @Draco18s It's a matter of style. As far as I'm concerned, `bool breakEarly` is just a silly way to avoid `goto` for religious reasons, and a lot harder to read :P On the other hand, I'm very happy that switch statements with bodies *don't* fall-through by default. C# was designed with "make the right thing easy, and the wrong thing hard" mentality, and they actually managed to achieve that... mostly. People don't change their minds all that often - you're often stuck with what feels "normal". – Luaan Apr 21 '17 at 07:26
  • Oh sure, definitely. Just saying that that's what I'm comfortable with. – Draco18s no longer trusts SE Apr 21 '17 at 12:30
1

The answer is that logic going in circles is best kept to religion and politics. Your default is really case 2, which means that case 2 is really just default. While it's possible that there's some execution in case 2 that doesn't occur in default, it's extremely rare that you'd ever need to do anything other than an if condition in your default case. Further, in troubleshooting the result of your switch evaluation cannot be immediately determined if you loop backward up the case chain. Imagine your stack trace, too.

There are times to use goto, but these are often in exceptional cases (see what I did there) where you need to immediately execute an action (such as logging something going wrong on another thread) before breaking a run condition or infinite loop. The general rule with goto is the same as with preprocessor commands. If there's another way you can do the same effective thing, you should use the other way for logical continuity and maintainability.

CDove
  • 1,940
  • 10
  • 19
  • _"Your 'default' is really 'case 2', which means that 'case 2' is really just 'default'"_ - hardly, given the fact in case of `case2` the code does additional code before jumping to `default` – schroedingersKat Apr 19 '17 at 13:50
  • It didn't in the example before this post. Still, that's addressed in the immediately following sentence. – CDove Apr 19 '17 at 13:51