38

For this program:

class Program
{
    static void Main(string[] args)
    {
        var state = States.One;
        switch (state)
        {
            case States.One:
                Console.WriteLine("One");
                break;
            case States.Zero:
                goto case States.One;
        }
    }
}

public enum States : ulong
{
    Zero = 0,
    One = 1,
}

I got:

"A switch expression or case label must be a bool, char, string, integral, enum, or corresponding nullable type"

But state variable is enum type. The error disappears if I comment the goto case line.

I am using VS 2013. + .NET 4.5.1.

Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
Brans Ds
  • 4,039
  • 35
  • 64
  • 1
    Compiles fine on mono with: http://www.compileonline.com/compile_csharp_online.php – Samuel May 12 '14 at 08:53
  • IF you remove ": ulong" part, would it work? – athabaska May 12 '14 at 08:53
  • 31
    Please, don't use `goto` it is considered a bad-practice – Max May 12 '14 at 08:54
  • @Samuel - i am using vs 2013. + .net 4.5.1. – Brans Ds May 12 '14 at 09:00
  • 25
    @MaxMommersteeg sometimes it is usefull and clear to not creates tens of voids for switch – Brans Ds May 12 '14 at 09:01
  • 2
    This bug is fixed in Roslyn. – Marc Gravell May 12 '14 at 09:09
  • @BransDs The performance of a `goto` statement is slower than a normal `break` and it shouldn't be used because of it makes code more complex + it isn't the natural way for the compiler to work, being forced to a different place in code this way. – Max May 12 '14 at 09:10
  • 20
    @MaxMommersteeg. It appears the OP is attempting to create a switch fall-thru which has to be done using the goto statement in C#. In C/C++ you don't need the goto for a fall-thru. Also, consider why "goto considered harmful" in the first place - it's because it can lead to spagetti code in un structured code. – user2425056 May 12 '14 at 09:11
  • @user2425056 You are right, a simple summary about goto: Goto may look faster and convenient. But it can actually confuse the runtime and result in poorer performance. In other words, goto is not only more complex for programmers, but is more difficult for the JIT compiler to optimize. – Max May 12 '14 at 09:13
  • 3
    @MaxMommersteeg, Do You have a link to some reference about the poor performance of goto in C#? – user2425056 May 12 '14 at 09:20
  • I most surely wouldn't want to document the enum for all possible 18,446,744,073,709,551,615 cases you can use it with. – Janne Matikainen May 12 '14 at 09:20
  • @user2425056 http://www.dotnetperls.com/goto there is a performance comparison in the article as well. – Max May 12 '14 at 09:21
  • 7
    @MaxMommersteeg: `goto` within `switch` is only mentioned in the end of that article. It refers to a [separate article about `goto` in `switch` on the same site](http://www.dotnetperls.com/goto-switch), which starts with the explanation "Goto is used inside switch. This **can enhance performance** and reduce code size in some cases." (emphasis by myself) – O. R. Mapper May 12 '14 at 09:26
  • 2
    @O.R.Mapper `in some cases` should be underlined and bold. – Max May 12 '14 at 09:27
  • @MarcGravell Don't suppose you can tell us why it's broken? :D – Rawling May 12 '14 at 13:53
  • @Rawling I have no clue; presumably simply a bad line of code – Marc Gravell May 12 '14 at 14:27
  • 6
    I think that `goto case` is probably the most-likely-to-be-valid usage of `goto` that exists in C#. – Tim S. May 12 '14 at 16:00
  • 1
    @MaxMommersteeg If you look at compiled IL, you'll see why the performance thing you said is probably incorrect. For example, these methods produce the same IL, which includes a goto-like instruction (`bge.s`, which jumps to a target instruction if `a` is greater than or equal to `b`), when compiled with optimization. http://pastebin.com/nmpJ2j8i – Tim S. May 12 '14 at 16:05
  • @BransDs I know your answer has already been answered, but you should consider reading up on "goto considered harmful", for instance here: http://stackoverflow.com/questions/46586/goto-still-considered-harmful – DigCamara May 13 '14 at 19:14
  • I don't understand why people think this use of "goto" is a bad practice. The same exact construct semantically works in C/C++ and no at that point says that "oh you're doing a branch which is technically a goto, so you shouldn't do that". – zumalifeguard May 29 '18 at 01:02

4 Answers4

64

This is known bug of the C# compiler when enum is typed as ulong and you use goto case at the same time. If you remove the ulong from enum, it compiles just fine. And because not many people run into this problem, they are not focusing on fixing it.

Karl Nicoll
  • 16,090
  • 3
  • 51
  • 65
Euphoric
  • 12,645
  • 1
  • 30
  • 44
6

Depending on your use case, this might also be an option for you:

switch (state)
{
    case States.Zero:
    case States.One:
        Console.WriteLine("One");
        break;
}

This should be working according to an example here: http://msdn.microsoft.com/de-de/library/06tc147t.aspx

T_D
  • 1,688
  • 1
  • 17
  • 28
4

You could use a label for goto instead of using the case directly in the goto statement:

switch (state)
{
    case States.One:
caseZeroRedirect:
        Console.WriteLine("One");
        break;
    case States.Zero:
        CouldDoSomethingFirst();
        goto caseZeroRedirect;
}
David S.
  • 5,965
  • 2
  • 40
  • 77
0

You should try this:-

switch (state)
{
 case States.Zero:
 case States.One:
    Console.WriteLine("1");
    break;
}
Iqbal Singh
  • 95
  • 1
  • 10