.NET编译器和"并非所有代码路径返回值"

Ric*_*bob 2 c# compiler-construction compiler-errors

为什么在如下代码中.NET编译器无法确定所有代码路径都返回值?

bool Test(bool param) {
    bool test = true;
    if (param)
        test = false;
    else
        test = false;
    if (!test)
        return false;
}
Run Code Online (Sandbox Code Playgroud)

错误CS0161:并非所有代码路径都返回值!

代码可以重构 - 但编译器不建议这样做.然而,所有返回路径都被覆盖 - 那么为什么编译器会抱怨它们不是?

编辑:我想这里的结论是:

(error CS0161) + (all code paths obviously return a value) => refactor code.  
Run Code Online (Sandbox Code Playgroud)

一旦你养成了翻译的习惯,我想一切都还可以.

Mic*_*urr 11

来自Visual Studio 2010附带的C#语言规范4.0.

10.6.10"方法体":

当方法的返回类型不为void时,该方法主体中的每个return语句都必须指定一个可隐式转换为返回类型的表达式.必须无法访问值返回方法的方法主体的端点.换句话说,在值返回方法中,不允许控制流出方法体的末尾.

可达性的定义在这里(强调添加):

8.1"终点和可达性":

如果可以通过执行来达到语句,则说该语句是可访问的.相反,如果不可能执行语句,则说该语句无法访问.

...

要确定特定语句或端点是否可访问,编译器将根据为每个语句定义的可访问性规则执行流分析.流分析考虑了控制语句行为的常量表达式(第7.19节)的值,但不考虑非常量表达式的可能值.

由于!test不是常量表达式(即使它总是会计算true),编译器也不得在流分析中考虑它.这种限制的一个原因(可能是唯一的原因)是在一般情况下进行这种流动分析是不可能的.

要消除错误,您需要returnelse子句中或在方法结束时无条件地使用另一个语句.

  • @Ricibob:我们制作可达性分析器的准确性越高,规范就越难以清楚地描述它,因此您越难以了解您的程序是否正确.今天指定的语言试图居住在算法可理解的"最佳位置",并且它捕获了大多数可达性错误.在优先级列表中,最小化"误报"错误的数量并不是很高.而且:错误指出你有机会改进代码; 对此感到高兴! (8认同)

dtb*_*dtb 10

来自Eric Lippert的博客:

可达性分析仪不是很聪明.它没有意识到只有两种可能的控制流,并且我们已经用返回覆盖了所有这些控制流.

(博客文章是关于switch语句的,但我想可达性分析器对于if语句来说并不聪明.)