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

Solution 1:

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:

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:

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