Why does C# allow statements after a case but not before it?

C#.NetSwitch Statement

C# Problem Overview


Why does C# allow this:

var s = "Nice";
switch (s)
{
    case "HI":
        break;
    const string x = "Nice";
    case x:
        Console.Write("Y");
        break;
}

But not this:

var s = "Nice";
switch (s)
{
    const string x = "Nice";
    case x:
        Console.Write("Y");
        break;
}

C# Solutions


Solution 1 - C#

Because your indentation is misleading, the first code actually is:

var s = "Nice";
switch (s)
{
    case "HI":
        break;
        const string x = "Nice";
    case x:
        Console.Write("Y");
        break;
}

That is, x is declared inside a case statement (though after a break), where it is valid. However, directly inside a switch statement it’s invalid – the only valid statements there are case and default.

Furthermore, const declarations are evaluated at compile time, so x is defined even though there’s a break statement before.

However, note that the Mono C# compiler will not compile this code, it complains that “the name ‘x’ does not exist in the current scope” so Mono seems to implement more checks than the .NET compiler. However, I can’t find any rules in the C# standard which forbid this use of the const declaration so I assume that the .NET compiler is right and the Mono compiler is wrong.

Solution 2 - C#

Because the language specification does not allow a const directly in your switch (only case and default are allowed):

switch (expression)
{
   case constant-expression:
      statement
      jump-statement
   [default:
      statement
      jump-statement]
}
 

Where:

>expression: An integral or string type expression.
>statement: The embedded statement(s) to be executed if control is transferred to the case or the default.
>jump-statement: A jump statement that transfers control out of the case body.
>constant-expression: Control is transferred to a specific case according to the value of this expression.

In the first case the const is part of your case logic. The const will is only working because it is rewritten at compiletime and not at runtime.

Solution 3 - C#

... because switch does this

jump_to_the_label_matchig(s)
{
   label1:
      ...
      done_quit_this;
   label2:
      ...
      done_quit_this;
   d'oh:
      ...
      done_quit_this;
}

and not this

now_jump_to_the_label_matchig(s)
{

   le'mme_wander_around_doing_things_that_could_have_been_done_before_me;

   label1:
      ...
      done_quit_this;
   label2:
      ...

I betcha that if that was allowed, you'd find people willing to do all their programming in there :-)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrtunerView Question on Stackoverflow
Solution 1 - C#Konrad RudolphView Answer on Stackoverflow
Solution 2 - C#PeterView Answer on Stackoverflow
Solution 3 - C#G. StoynevView Answer on Stackoverflow