Почему C# разрешает операторы после случая, но не до него?


почему C# позволяет этой:

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;
}
3 64

3 ответа:

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

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

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

кроме того, const декларации оцениваются во время компиляции, так что x определяется, даже если есть break заявление до.

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

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

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

где:

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

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

... потому что 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:
      ...

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