为什么C#允许在一个案例之后但不在它之前的语句?

时间:2013-05-22 14:16:36

标签: c# .net switch-statement

为什么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 个答案:

答案 0 :(得分:119)

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

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

也就是说,xcase语句中声明(尽管在break之后),它是有效的。但是,直接在switch语句中它是无效的 - 唯一有效的语句有casedefault

此外,const声明在编译时进行评估,因此即使之前有x语句,也会定义break

但是,请注意Mono C#编译器将无法编译此代码,它抱怨“当前范围中不存在名称'x'”因此Mono似乎实现了比.NET编译器更多的检查。但是,我在C#标准中找不到任何禁止使用const声明的规则,所以我假设.NET编译器是正确的,Mono编译器是错误的。

答案 1 :(得分:7)

因为语言规范不允许在您的交换机中直接使用const(仅允许大小写和默认值):

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

其中:

  

expression: 整数或字符串类型表达式    statement: 如果控件转移到案例或默认情况下要执行的嵌入式语句。
   jump-statement: 将控件移出案件正文的跳转声明    constant-expression: 根据此表达式的值将控件转移到特定案例。

在第一种情况下,const是案例逻辑的一部分。 const只会起作用,因为它在编译时而不是在运行时重写。

答案 2 :(得分: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:
      ...

我认为,如果允许的话,你会发现有人愿意在那里做所有的编程: - )