Eri*_*ert 13
这个问题有点不清楚,但我会考虑一下.
首先,Adam的答案是正确的,因为编译器根据"优化"开关是打开还是关闭而发出的IL存在差异.编译器在开启优化开关时更加积极地删除无法访问的代码.
有两种相关的无法访问的代码.首先是法律上无法达到的代码; 也就是说,C#语言规范称之为无法访问的代码.第二,事实上无法达到的代码; 这是C#规范没有调用为无法访问的代码,但无法访问.在后一种无法访问的代码中,优化器已知的代码是不可访问的,并且优化器不知道代码是不可达的.
编译器通常总是删除法律上无法访问的代码,但只有在优化器打开时才会删除事实上无法访问的代码.
以下是每个例子:
int x = 123;
int y = 0;
if (false) Console.WriteLine(1);
if (x * 0 != 0) Console.WriteLine(2);
if (x * y != 0) Console.WriteLine(3);
Run Code Online (Sandbox Code Playgroud)
所有三个Console.WriteLines都无法访问.第一个是法律上无法到达的; C#编译器声明为了明确的赋值检查,必须将此代码视为无法访问.
第二个是法律上可以到达但事实上无法到达.必须检查它们是否存在明确的分配错误,但允许优化器删除它们.
在这两者中,优化器检测到(2)情况但不检测(3)情况.优化器知道整数乘以零始终为零,因此条件始终为false,因此它会删除整个语句.
在(3)情况下,优化器不跟踪分配给y的可能值,并确定y在乘法点始终为零.即使你和我知道结果无法到达,优化器也不知道.
有关明确赋值检查的内容如下:如果您有一个无法访问的语句,则认为所有本地变量都在该语句中分配,并且所有赋值都被认为不会发生:
int z;
if (false) z = 123;
Console.WriteLine(z); // Error
if (false) Console.WriteLine(z); // Legal
Run Code Online (Sandbox Code Playgroud)
第一种用法是非法的,因为z在使用时尚未明确分配.第二种用法不是非法的,因为代码甚至无法访问; z在分配之前无法使用,因为控件永远不会到达!
C#2有一些错误,它混淆了两种可达性.在C#2中你可以这样做:
int x = 123;
int z;
if (x * 0 != 0) Console.WriteLine(z);
Run Code Online (Sandbox Code Playgroud)
并且编译器不会抱怨,即使在法律上可以访问对Console.WriteLine的调用.我在C#3.0中解决了这个问题,我们采取了改变.
请注意,我们保留随时更改无法访问的代码检测器和代码生成器的工作方式的权利.我们可能决定总是发出无法访问的代码或从不发出它或其他什么.
| 归档时间: |
|
| 查看次数: |
514 次 |
| 最近记录: |