VS.NET 2010对C#常数表达式的评估
当我在Visual Studio中尝试C#中的示例表达式时VS.NET 2010对C#常数表达式的评估,c#,visual-studio,C#,Visual Studio,当我在Visual Studio中尝试C#中的示例表达式时 public int Test() { if (10/2 == 5) throw new Exception(); return 0; } 当我保持表达式10/2==5时,vs.net会自动抛出一个警告“检测到无法访问的代码” 如果我更改表达式10/2==6,IDE会高兴吗?这是怎么发生的 编辑:对不起,问题不完整。它会立即发生,甚至在编译代码之前就发生了 我对每个答复都投了赞成票,并在先进先出的基础上
public int Test()
{
if (10/2 == 5)
throw new Exception();
return 0;
}
当我保持表达式10/2==5时,vs.net会自动抛出一个警告“检测到无法访问的代码”
如果我更改表达式10/2==6,IDE会高兴吗?这是怎么发生的
编辑:对不起,问题不完整。它会立即发生,甚至在编译代码之前就发生了
我对每个答复都投了赞成票,并在先进先出的基础上接受了第一个答复
if (10/2 == 5)
将始终返回true,这意味着
throw new Exception();
将始终执行,并且
return 0;
永远不会到达在第一种情况下,编译器处理表达式
10/2==5
,该表达式的计算结果为true,因此引发异常,并且返回0
语句不可到达
在第二种情况下,10/2==6
的计算结果为false,因此可以访问return0
语句,因为不会引发异常
为了响应您的编辑:您的代码不必实际编译,编译器才能知道代码行是不可访问的。知道
10/2==5
始终为真是明智之举,不管用户输入什么,这意味着异常将始终被抛出 有人抱怨说
return 0;
永远联系不到。10/2始终等于5。如果反编译此代码,您将得到:
public int Test()
{
throw new Exception();
}
我相信,因为这些都是常量值,所以数学运算是在编译时完成的,所以10/2实际上不是10/2,而是5…因此,编译器意识到5==5始终是真的就变得微不足道了。事实上,我相信这些常数会自动转化为真。编译器的目标是优化总是要在编译时重复并运行处理的代码,而不是反复运行相同的处理
因此,基本上,编译器认识到,由于if总是true
,并且if会导致返回
(通过抛出
),因此它会优化它知道永远不会执行的代码。因此,反编译代码会产生上述结果
事实上,如果您执行10/2==6
,则会发生相反的情况,它被“恒定化”为5==6,并被转换为false。由于if始终为false,因此它优化了if:
public int Test()
{
int num = 0;
return num;
}
编译器足够聪明(这是一个非常简单的检查),并确定永远不会到达返回0。这是因为10/2==5将始终为真。根据编译器,以下表达式的计算结果相等
if (10/2 == 5)
或
编译器之所以能够确定这一点,是因为数字不是可变的。事实上,他知道他永远不会进来 返回0 他只是警告说,10/2==5以下的整个代码永远不会被解释为10/2始终是5 同样地:
if (true)
{
......
}
else
{
.....
}
正如其他人所说,编译器可以计算表达式
10/2==5
编译时,因为它是一个常量表达式。它的计算结果为true
,因此范围之后的任何代码都是不可读取的。如果更改为false
,则无法访问If
中的代码
所以现在考虑这个代码:
public int TestA()
{
if (10 / 2 == 5)
return 1;
return 0;
}
public int TestB()
{
if (10 / 2 == 6)
return 1;
return 0;
}
这两种方法都会生成关于无法访问代码的警告
C#编译器的奇怪之处在于,如果无法访问的代码完全由throw
语句组成,则不会发出关于无法访问的警告
添加:所以现在编译器是he;Pnobody回答了真正的问题:为什么编译器不抱怨在第二种情况下无法访问异常?@codesparkle我刚才在回答中提到了这一点。
public int TestA()
{
if (10 / 2 == 5)
return 1;
return 0;
}
public int TestB()
{
if (10 / 2 == 6)
return 1;
return 0;
}