Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use a 'goto' in a switch?

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?

like image 348
Brent Arias Avatar asked Jan 21 '11 06:01

Brent Arias


People also ask

Can goto be used in switch?

A label is a valid C# identifier followed by colon. In this case, case and default statements of a Switch are labels thus they can be targets of a goto. However, the goto statement must be executed from within the switch. that is we cannot use the goto to jump into switch statement .

Can we use goto statement in switch case?

@The Smartest: A switch statement in itself can already have plenty of goto s, but they are named differently: Each break is a goto. @chiccodoro That's nothing, actually each case is a label and switch essentially is a goto . Each break is a goto , but also each continue is a goto too.

Can goto statement go outside of switch?

Yes, it does.

Why goto is not recommended?

NOTE − Use of goto statement is highly discouraged in any programming language because it makes difficult to trace the control flow of a program, making the program hard to understand and hard to modify. Any program that uses a goto can be rewritten to avoid them.


4 Answers

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.

like image 83
mmx Avatar answered Oct 18 '22 05:10

mmx


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;
}
like image 32
Zooba Avatar answered Oct 18 '22 05:10

Zooba


   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;
}
like image 8
djeeg Avatar answered Oct 18 '22 05:10

djeeg


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

like image 6
Robert T. Adams Avatar answered Oct 18 '22 05:10

Robert T. Adams