Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么C#允许在案例之后而不允许在案例之前进行陈述?_C#_.net_Switch Statement - Fatal编程技术网

为什么C#允许在案例之后而不允许在案例之前进行陈述?

为什么C#允许在案例之后而不允许在案例之前进行陈述?,c#,.net,switch-statement,C#,.net,Switch Statement,为什么C#允许这样做: 但不是这个: 因为缩进有误导性,第一个代码实际上是: var s = "Nice"; switch (s) { case "HI": break; const string x = "Nice"; case x: Console.Write("Y"); break; } 也就是说,x在case语句中声明(尽管在break之后),在该语句中它是有效的。但是,直接在开关语句中无效–唯一有效的语句

为什么C#允许这样做:

但不是这个:


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

var s = "Nice";
switch (s)
{
    case "HI":
        break;
        const string x = "Nice";
    case x:
        Console.Write("Y");
        break;
}
也就是说,
x
case
语句中声明(尽管在
break
之后),在该语句中它是有效的。但是,直接在
开关
语句中无效–唯一有效的语句是
大小写
默认值

此外,
const
声明在编译时进行求值,因此即使前面有
break
语句,也定义了
x


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

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

其中:

表达式:
整数或字符串类型的表达式。
语句:
如果控制权转移到案例或默认值,则要执行的嵌入式语句。
跳转语句:
将控制权从箱体中转移出去的跳转语句。
常量表达式:
根据此表达式的值将控件转移到特定案例


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

。。。因为
开关
会执行此操作

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:
      ...

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

任何其他语言都允许吗?你为什么要这样做?是否有人会写这样的代码,这仍然是一个有趣的问题。在幕后一定有一些奇怪的范围界定工作。@r case语句之所以需要是编译时常量,是因为
switch
的实现是一个字典,而不是一系列
if/else if
语句。它需要它们生成一个可以作为字典键的对象。同样重要的是,没有评估案例的副作用,因为当测试用例时,这些副作用不会产生,比如说C++,谢谢你发布这个问题;我将把这一个添加到我的开关古怪和微妙的单声道错误列表中。如果您对switch语句的不寻常用法感兴趣,请参阅我关于该主题的文章:但如果它真的中断了,它为什么会显示y?@rtuner
const
语句不是在运行时执行的,而是在编译时替换的。试着在它上面放一个断点。但是为什么在断点之后和下一个案例之前允许任何代码?@Magnus为什么允许你在
返回之后放代码在该范围结束之前?这是无法运行的代码。答案很简单,因为他们没有费心将其定为非法;将其定为非法不仅仅是离开它,而且离开它并不会真正引起问题。禁止它的功能请求根本不值得努力去实现。最后一段:的确,Mono在这里似乎是错误的。但人们很难责怪他们;这是一个奇怪的场景。我想知道Mono是否对switch语句中的作用域的其他规则有错误?我会发现的!
switch (expression)
{
   case constant-expression:
      statement
      jump-statement
   [default:
      statement
      jump-statement]
}
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:
      ...