5

当我在 Visual Studio 中尝试 C# 中的示例表达式时

public int Test()
{
    if (10/2 == 5)
        throw new Exception();
    return 0;
}

当我保留表达式 10/2 == 5 时,vs.net 会自动抛出警告“检测到无法访问的代码”。

如果我更改表达式 10/2 == 6,IDE 是否满意?它是如何发生的?

编辑:对不起,不完整的问题。它发生得如此迅速,甚至在编译代码之前就发生了?

我对每个回复都投了赞成票,并在 FIFO 的基础上接受了第一个答案

4

7 回答 7

9
if (10/2 == 5)

将始终返回 true,这意味着

throw new Exception();

将永远被执行,并且

return 0;

永远不会到达

于 2012-08-14T14:45:04.257 回答
4

如果你反编译这段代码,你最终会得到:

public int Test()
{
     throw new Exception();
}

我相信,由于这些是常数值,所以数学是在编译时完成的,所以 10/2 并不是真正的 10/2,而是 5...所以编译器意识到 5==5 总是微不足道的会是真的。事实上,我相信这些常量会自动转换为 true。编译器的目标是优化总是会重复并在编译时运行它的处理的代码,而不是一遍又一遍地运行相同的处理。

因此,基本上,编译器意识到,由于 if 始终是true并且 if 导致 a return(通过 a throw),所以它优化了它知道永远不会执行的代码。因此,反编译的代码结果如上。

事实上,如果你这样做,就会发生相反的情况10/2 == 6,它被“常量化”为 5 == 6,它变成了 false。由于 if 总是为假,它优化了 if:

public int Test()
{
    int num = 0;
    return num;
}
于 2012-08-14T14:47:10.907 回答
4

正如其他人所说,编译器可以在编译时评估表达式10 / 2 == 5,因为它是一个常量表达式。它评估为true,因此范围之后的任何代码if都是不可用的。如果更改为,则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语句组成,则不会发出有关无法访问的警告。

补充:这个 Stack Overflow 问题是相关的

于 2012-08-14T15:11:51.227 回答
3

有人抱怨这条线

return 0;

永远无法到达。10/2 总是等于 5。

于 2012-08-14T14:46:09.470 回答
2

在第一种情况下,编译器处理表达式10/2 == 5,其计算结果为真,因此抛出异常并且return 0语句不可访问。

在第二种情况下,10/2 == 6计算结果为 false,因此该return 0语句是可访问的,因为没有引发异常。

作为对您的编辑的回应:您的代码不必实际编译,编译器就可以知道该代码行无法访问。无论任何用户输入如何,知道这10/2 == 5始终是真的是足够聪明的,这意味着总是会抛出异常。

于 2012-08-14T14:45:51.930 回答
1

编译器足够聪明(这是一个非常简单的检查)并确定永远不会达到 return 0。这是因为 10/2 == 5 永远为真。根据编译器,以下表达式的计算结果相同

if (10/2 == 5)

或者

if true

编译器能够确定这一点的原因是数字不是可变的。

于 2012-08-14T14:48:49.510 回答
1

事实上他知道他永远不会回来 0

他只是警告说,10/2 == 5 以下的整个代码永远不会被解释为 10/2 永远是 5。

以同样的方式:

if (true)
{
     ......
}
else 
{
  .....
}
于 2012-08-14T14:49:52.413 回答