64

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

3 回答 3

120

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

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

也就是说,x在声明中case声明(尽管在 a 之后break),它是有效的。但是,直接在switch语句中是无效的——唯一有效的语句是caseand default

此外,声明是在编译时const评估的,因此即使之前有声明也是如此。xbreak

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

于 2013-05-22T14:18:23.160 回答
7

因为语言规范不允许 const 直接在您的开关中(仅允许大小写和默认值):

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

在哪里:

expression:整数或字符串类型的表达式。
statement:如果将控制权转移到案例或默认值,则要执行的嵌入语句。
jump-statement:将控制权转移到案例主体之外的跳转语句。
constant-expression:根据此表达式的值将控制转移到特定情况。

在第一种情况下, const 是您的案例逻辑的一部分。const will 之所以有效,是因为它是在编译时而不是在运行时重写的。

于 2013-05-22T14:20:18.327 回答
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:
      ...

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

于 2013-05-30T03:34:40.130 回答