为什么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; } 

因为你的缩进是误导性的,所以第一个代码实际上是:

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

也就是说, x是在一个case语句中声明的(尽pipe在break ),它是有效的。 但是,直接在switch语句中它是无效的 – 唯一有效的语句是casedefault

此外, const声明是在编译时计算的 ,所以即使之前有一个break语句, x被定义。

但是,请注意,Mono C#编译器不会编译这个代码,它抱怨说“名称x在当前范围中不存在”,所以Mono似乎比.NET编译器执行更多的检查。 但是,我不能在C#标准中find任何禁止使用const声明的规则,所以我认为.NET编译器是正确的,Mono编译器是错误的。

由于语言规范不允许在你的交换机中直接使用const(只允许case和default):

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

哪里:

expression:整型或string型expression式。
statement:如果控制转移到大小写或默认值,则embedded语句将被执行。
jump-statement:将控制权转移出案例主体的跳转语句。
constant-expression:根据此expression式的值,将控件转移到特定的情况。

在第一种情况下,const是你的案例逻辑的一部分。 常量只能在编译时重写,而不是在运行时重写。

…因为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: ... 

我敢打赌,如果这是允许的,你会发现人们愿意在那里做所有的编程:-)