2013-05-22 2 views
63

Почему 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; 
} 
+8

Есть ли на вашем языке русский язык? – Vivasaayi

+50

Почему вы тоже хотите? – Jodrell

+12

Независимо от того, будет ли кто-нибудь писать такой код, это еще интересный вопрос. Должно быть какое-то странное вещание, которое происходит за кулисами. –

ответ

119

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

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

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

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

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

+2

Но как же оно отображает y, если оно действительно ломается? – rtuner

+1

@rtuner Я думаю, потому что объявление 'const' перемещается в начало метода во время компиляции. – CodeCaster

+21

Операторы @rtuner 'const' не выполняются во время выполнения, они заменяются во время компиляции. Попробуйте и наложите на него точку останова. – Jodrell

7

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

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

Где:

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

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

1

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

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

Смежные вопросы