常量和编译时评估 - 为什么要更改此行为

时间:2012-01-24 04:12:52

标签: c# compiler-construction compiler-optimization inference

如果你向Eric Lippert转发到此video大约13分钟,他描述了对C#编译器所做的更改,该更改导致以下代码无效(显然在.NET 2之前和之后,此代码将具有编译)。

int y;
int x = 10;
if (x * 0 == 0)
    y = 123;

Console.Write(y);

现在我明白,上面代码的任何执行实际上都会计算到

int y;
int x = 10;
y = 123;
Console.Write(y);

但是我不明白为什么将下面的代码编译成“可编辑”被认为是“可取的”? IE:允许这样的推论运行的风险是什么?

1 个答案:

答案 0 :(得分:3)

规范规定,仅在if块内分配的事物的明确赋值是不确定的。该规范没有说明删除不必要的if块的编译器魔法。特别是,当您更改if条件时,它会产生一个非常令人困惑的错误消息,并突然收到关于y未被分配的错误“嗯?分配y时我没有改变!”

编译器可以自由地执行它想要的任何明显的代码删除,但是首先它需要遵循规则的规范。

具体而言,第5.3.3.5节(MS 4.0规范):

  

5.3.3.5如果陈述   对于表单的if语句stmt:

     

if ( expr ) then-stmt else else-stmt

     
      
  • v在expr的开头和stmt的开头具有相同的明确赋值状态。
  •   
  • 如果v在expr的末尾明确赋值,那么如果没有else子句,那么它肯定会在控制流转移到then-stmt和else-stmt或stmt的终点。 / LI>   
  • 如果v在expr结尾处具有“在真实表达式后明确赋值”的状态,那么它肯定会在控制流转移到then-stmt时分配,并且在控制流转移到其他任何一个时都没有明确分配如果没有其他条款,则为stmt的终点。
  •   
  • 如果v在expr结尾处具有“在假表达后明确赋值”的状态,则它在控制流转移到else-stmt时明确赋值,并且在控制流转移到then-stmt时没有明确赋值。当且仅当它在then-stmt的终点明确赋值时,它才明确地分配给stmt的终点。
  •   
  • 否则,在控制流转移到then-stmt或else-stmt或者没有其他的stmt的结束点时,v被认为没有明确分配
  •   
     

对于要在某个位置明确分配的初始未分配变量,必须在通往该位置的每个可能执行路径中对变量进行赋值。

技术上,执行路径存在if条件为假的情况;如果在y中也分配了else,那么很好,但是...规范明确规定不要求发现if条件总是如此。