Ken*_*Kin 16 c# switch-statement unreachable-code
从一个-5问题再次启发!
我读了@Quartermeister的 [ 评论 ] 并感到惊讶!
那么为什么这会编译
switch(1) {
case 2:
}
Run Code Online (Sandbox Code Playgroud)
但事实并非如此.
int i;
switch(i=1) {
case 2: // Control cannot fall through from one case label ('case 2:') to another
}
Run Code Online (Sandbox Code Playgroud)
这不是
switch(2) {
case 2: // Control cannot fall through from one case label ('case 2:') to another
}
Run Code Online (Sandbox Code Playgroud)
更新:
该-5问题变得-3.
Eri*_*ert 21
他们都不应该编译.C#规范要求switch部分至少有一个语句.解析器应该禁止它.
让我们忽略解析器允许空语句列表的事实; 这不是什么相关的.规范说开关部分的末端必须没有可达到的终点; 这是相关的一点.
在上一个示例中,交换机部分具有可到达的终点:
void M(int x) { switch(2) { case 2: ; } }
Run Code Online (Sandbox Code Playgroud)
所以一定是个错误.
如果你有:
void M(int x) { switch(x) { case 2: ; } }
Run Code Online (Sandbox Code Playgroud)
然后编译器不知道x是否会是2.它保守地假定它可以,并且说该部分具有可到达的终点,因为交换机案例标签是可达的.
如果你有
void M(int x) { switch(1) { case 2: ; } }
Run Code Online (Sandbox Code Playgroud)
然后,编译器可以推断端点不可访问,因为无法访问案例标签.编译器知道常量1永远不会等于常量2.
如果你有:
void M(int x) { switch(x = 1) { case 2: ; } }
Run Code Online (Sandbox Code Playgroud)
要么
void M(int x) { x = 1; switch(x) { case 2: ; } }
Run Code Online (Sandbox Code Playgroud)
然后你知道并且我知道终点是不可达的,但编译器不知道这一点.规范中的规则是可达性仅通过分析常量表达式来确定.包含变量的任何表达式,即使您通过其他方式知道其值,也不是常量表达式.
在过去,C#编译器存在错误,而事实并非如此.你可以这样说:
void M(int x) { switch(x * 0) { case 2: ; } }
Run Code Online (Sandbox Code Playgroud)
并且编译器会推断x*0必须为0,因此无法访问case标签.这是一个bug,我在C#3.0中修复过.规范说只有常量用于该分析,并且x是变量,而不是常量.
现在,如果程序是合法的,那么编译器可以使用这样的高级技术来影响生成的代码.如果你说的话:
void M(int x) { if (x * 0 == 0) Y(); }
Run Code Online (Sandbox Code Playgroud)
然后编译器可以生成代码,就像您编写的那样
void M(int x) { Y(); }
Run Code Online (Sandbox Code Playgroud)
如果它想要的话.但它不能使用x * 0 == 0确定语句可达性的事实.
最后,如果你有
void M(int x) { if (false) switch(x) { case 2: ; } }
Run Code Online (Sandbox Code Playgroud)
然后我们知道交换机是不可达的,因此该块没有可达到的终点,所以这令人惊讶地是合法的.但鉴于上面的讨论,你现在知道了
void M(int x) { if (x * 0 != 0) switch(x) { case 2: ; } }
Run Code Online (Sandbox Code Playgroud)
不x * 0 != 0视为false,因此终点被认为是可达的.
| 归档时间: |
|
| 查看次数: |
977 次 |
| 最近记录: |