Почему С# разрешает инструкции после случая, но не раньше?

Почему С# разрешает это:

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

Но не это:

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

Ответ 1

Поскольку ваш отступы вводят в заблуждение, первый код на самом деле:

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

То есть x объявляется внутри оператора case (хотя после break), где он действителен. Однако непосредственно внутри оператора switch его значение недействительно - единственными действительными утверждениями являются case и default.

Кроме того, объявления const оцениваются во время компиляции, поэтому x определяется, даже если это предложение a break.

Однако обратите внимание, что компилятор Mono С# не компилирует этот код, он жалуется, что "имя" x не существует в текущей области ", поэтому Mono, похоже, выполняет больше проверок, чем компилятор .NET. Однако я не могу найти какие-либо правила в стандарте С#, которые запрещают это использование объявления const, поэтому я предполагаю, что компилятор .NET прав, а компилятор Mono ошибочен.

Ответ 2

Поскольку спецификация языка не позволяет const непосредственно в вашем коммутаторе (разрешены только случай и значение по умолчанию):

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

Где:

expression: Интегральное или строковое выражение.
statement: Встроенный оператор (ы), который должен быть выполнен, если управление передано в случае или по умолчанию.
jump-statement: Оператор перехода, который передает управление из корпуса.
constant-expression: Управление передается в конкретный случай в соответствии со значением этого выражения.

В первом случае const является частью вашей логики case. Команда const будет работать только потому, что она переписывается в compiletime, а не во время выполнения.

Ответ 3

... потому что switch делает это

jump_to_the_label_matchig(s)
{
   label1:
      ...
      done_quit_this;
   label2:
      ...
      done_quit_this;
   d'oh:
      ...
      done_quit_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:
      ...

Я уверен, что если бы это было разрешено, вы бы нашли людей, готовых сделать все свое программирование там: -)