Use a 'goto' in a switch?

57,013

Solution 1

This construct is illegal in C#:

switch (variable) {
   case 2: 
       Console.WriteLine("variable is >= 2");
   case 1:
       Console.WriteLine("variable is >= 1");
}

In C++, it would run both lines if variable = 2. It may be intentional but it's too easy to forget break; at the end of the first case label. For this reason, they have made it illegal in C#. To mimic the fall through behavior, you will have to explicitly use goto to express your intention:

switch (variable) {
   case 2: 
       Console.WriteLine("variable is >= 2");
       goto case 1;
   case 1:
       Console.WriteLine("variable is >= 1");
       break;
}

That said, there are a few cases where goto is actually a good solution for the problem. Never shut down your brain with "never use something" rules. If it were 100% useless, it wouldn't have existed in the language in the first place. Don't use goto is a guideline; it's not a law.

Solution 2

C# refuses to let cases fall through implicitly (unless there is no code in the case) as in C++: you need to include break. To explicitly fall through (or to jump to any other case) you can use goto case. Since there is no other way to obtain this behaviour, most (sensible) coding standards will allow it.

switch(variable)
{
case 1:
case 2:
    // do something for 1 and 2
    goto case 3;
case 3:
case 4:
    // do something for 1, 2, 3 and 4
    break;
}

A realistic example (by request):

switch(typeOfPathName)
{
case "relative":
    pathName = Path.Combine(currentPath, pathName);
    goto case "absolute";

case "expand":
    pathName = Environment.ExpandEnvironmentVariables(pathName);
    goto case "absolute";

case "absolute":
    using (var file = new FileStream(pathName))
    { ... }
    break;

case "registry":
    ...
    break;
}

Solution 3

   public enum ExitAction {
        Cancel,
        LogAndExit,
        Exit
    }

This is neater

ExitAction action = ExitAction.LogAndExit;
switch (action) {
    case ExitAction.Cancel:
        break;
    case ExitAction.LogAndExit:
        Log("Exiting");
        goto case ExitAction.Exit;
    case ExitAction.Exit:
        Quit();
        break;
}

Than this (especially if you do more work in Quit())

ExitAction action = ExitAction.LogAndExit;
switch (action) {
    case ExitAction.Cancel:
        break;
    case ExitAction.LogAndExit:
        Log("Exiting");
        Quit();
        break;
    case ExitAction.Exit:
        Quit();
        break;
}

Solution 4

In addition to using goto case, you can goto a label that is in another case clause:

    switch(i) {
    case "0":
        // do some stuff
        break;
    case "1":
        // other stuff, then "fall through" to next case clause
        goto Case2;
    case "2":
    Case2:
        break;
    }

This way, you can jump to another case clause without worrying about the value or type of the expression.

Some sort of explicit "fallthrough" keyword that can be substituted for break would have been nice, though...

Solution 5

It's the only way that C# allows a switch case 'fallthrough'. In C# (unlike C, C++ , or Java), a case block in a switch statement must end with a break or some other explicit jump statement.

Share:
57,013
Brent Arias
Author by

Brent Arias

Brent is a full-stack, hands-on software and cloud architect. He can be reached at [email protected]. LinkedIn profile My company AxisCode

Updated on July 09, 2022

Comments

  • Brent Arias
    Brent Arias almost 2 years

    I've seen a suggested coding standard that reads Never use goto unless in a switch statement fall-through.

    I don't follow. What exactly would this 'exception' case look like, that justifies a goto?

  • Greg Sansom
    Greg Sansom over 13 years
    That's what the sentence means, but the question is why is this justified?
  • jcopenha
    jcopenha over 13 years
    The question was "What exactly would this 'exception' case look like". The fact that there is no alternative in C# is what justifies it.
  • Greg Sansom
    Greg Sansom over 13 years
    What would the exception case look like, not the implementation. ie in what circumstance would you want to do this.
  • jcopenha
    jcopenha over 13 years
    You can't goto case of enumerations - it has to be a constant. A shame really, since it would be handy, but that appears to be the behaviour.
  • jcopenha
    jcopenha over 13 years
    "This exception case" refers to "in a switch-statement fallthrough," the use of the word "unless" indicating an exception to the general rule of "never use" that was specified before the subject, "goto." (Stop me if I'm going too fast.)
  • djeeg
    djeeg over 13 years
    err, yes you can, enumerations are treated as constants
  • jcopenha
    jcopenha over 13 years
    Gah, must've mistyped something when I tested it earlier. It compiles now... I swear it didn't before. Sorry. +1
  • Robert T. Adams
    Robert T. Adams about 12 years
    I just realized this is a year old; sorry about that! I'm still stuck in 2011.
  • moskalak
    moskalak over 10 years
    It might be necromancy, but it's the good type of necromancy. It actually helped me. :) +1'd
  • curiousBoy
    curiousBoy over 9 years
    @Mehrdad: I would love to read "Never shut down your brain" but I think Im kinda late for it.. It seems it has been removed. Is that possible to refresh the link if you have any other reference link by chance? Thanks
  • mmx
    mmx over 9 years
    @curiousBoy Unfortunately, I do not recall what it was after more than 3 years and I do not have enough rep on access programmers.stackexchange to see it (I suspect it used to be a Stack Overflow post I linked to).
  • Filip Cornelissen
    Filip Cornelissen almost 9 years
    you can also use: goto case "2";
  • ThrowingDwarf
    ThrowingDwarf about 8 years
    That is unfortunate, even 5 years after the initial post it is still relevant
  • ThrowingDwarf
    ThrowingDwarf about 8 years
    True point.The funny part is that this counts for nearly everything, not just for devices. A gun for example, its not the weapon on the table that does any harm, its the person who uses it. It can also be used for good things like protecting someone that is being robbed. It ENTIRELY depends on the user.
  • Matthew Lock
    Matthew Lock almost 7 years
    Shame that link for "Never shut down your brain" is gone. I wish SO would allow certain opinionated questions and answers as it makes life fun. Here's a similar question stackoverflow.com/questions/406760/…
  • Jessica Pennell
    Jessica Pennell almost 7 years
    Found it, stackoverflow.com/questions/406760/… edited Jan 9 '09 at 15:52 Steven Robbins (stackoverflow.com/users/26507) Just in case, the original comment is below. Camel case at the beginning to get around more restrictive character limit than existed in '09
  • Jessica Pennell
    Jessica Pennell almost 7 years
    TheOnly "best practice" youShouldBeUsingAllTheTimeIs "Use Your Brain". Too many people jumping on too many bandwagons and trying to force methods, patterns, frameworks etc onto things that don't warrant them. Just because something is new, or because someone respected has an opinion, doesn't mean it fits all :) EDIT: Just to clarify - I don't think people should ignore best practices, valued opinions etc. Just that people shouldn't just blindly jump on something without thinking about WHY this "thing" is so great, IS it applicable to what I'm doing, and WHAT benefits/drawbacks does it bring?
  • Jessica Pennell
    Jessica Pennell almost 7 years
    I'm not cool enough to edit that 406760 link into Mehrdad Afshari's answer, if someone with enough karma could and could delete this comment it would be appreciated by everyone I'm sure.
  • Krythic
    Krythic over 4 years
    I was recently coding an Item generator, and for Legendary items, if no matching base type exists, I use goto to ensure the player gets a rare quality item instead. It certainly beats a convoluted recursion mechanism.
  • jeffbRTC
    jeffbRTC about 3 years
    I'd love the evil. Thanks.. Gonna to use it now!
  • Jonas Äppelgran
    Jonas Äppelgran almost 2 years
    There is also goto default;.