.NET编译器和“并非所有的代码路径返回一个值”(.NET compiler and “Not al

2019-06-23 13:40发布

为什么在代码中像下面是.NET编译器不能够确定,所有的代码路径都返回值?

bool Test(bool param) {
    bool test = true;
    if (param)
        test = false;
    else
        test = false;
    if (!test)
        return false;
}

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

该代码可以重构 - 但是编译器不提示。 然而,所有的返回路径覆盖 - 所以为什么编译器抱怨说,他们都没有?

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

(error CS0161) + (all code paths obviously return a value) => refactor code.  

一旦你得到翻译的习惯,我想一切正常。

Answer 1:

从包含在Visual Studio 2010中的C#语言规范4.0。

10.6.10“法体”:

当一个方法的返回类型不是void,在该方法的身体每一个return语句必须指定隐式转换为返回类型的表达式。 一个返回值的方法的方法体的端点必须是不可到达的。 换句话说,在一个返回值的方法时,控制不允许流出方法体的端部。

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

8.1“结束点和可到达”:

如果一个语句可能通过执行来达到,该声明被认为是可达的。 反之,如果没有一个语句将被执行的可能性,该声明被认为是不可到达的。

...

为了确定一个特定语句或结束点是否可到达,编译器根据为每个语句中定义的可达性规则流分析。 流分析考虑到控制语句行为的常量表达式(§7.19)的值,但非恒定表达的可能值不考虑

由于!test不是一个常量表达式(即使它会始终评估为true ),编译有义务不考虑它的流动分析。 原因之一(也许是唯一的原因),这种限制是进行这种类型的流量分析,在一般情况下是不可能的。

为了摆脱错误的,你需要有另一种return声明,无论在else无条件地在方法的最后条款或。



Answer 2:

从埃里克利珀的博客 :

可达性分析是不是很聪明。 它没有意识到,只有两种可能的控制流,我们已经覆盖了所有他们与回报。

(本博客文章是对switch语句,但我估计可达性分析是不是要聪明得多if报表。)



Answer 3:

这只是表示该编译器是多么聪明关于什么被初始化和线路将执行的限制。

我碰到这样不时。 但它很少,这是一个问题。 我通常只重组代码一点。



Answer 4:

让我们落后的分析代码:

问题:代码不返回任何值。

问:凡在代码返回一个值?

答:就在最后一行。

结论:所以代码(最后一行)的该行应该总是返回一个值。

问:请问最后一行总是返回一个值?

答:不,它只有返回值testfalse ,而它已经被设置为true在第一线。

结论:由于编译器说,虽然它应该返回这个函数永远没有返回值bool



Answer 5:

相反,在很多细节去的,让我回答您的问题直接。

  1. 函数返回类型被指定为布尔因此函数必须返回true或false
  2. PARAM已被定义为因此不能在编译时来确定它的值的输入参数
  3. 测试变量的值是依赖于PARAM和按照步骤-2,不能在编译时来确定参数值的方式 ,因此不能在编译时来确定测试的值
  4. 作为试验的值不被称为编译时(按照步骤-3)因而开始寻找其他/默认根如果(!测试),因此它抛出错误。

谢谢



文章来源: .NET compiler and “Not all code paths return a value”