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

时间:2012-04-11 21:27:57

标签: c# compiler-construction compiler-errors

为什么在如下代码中,.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.  

一旦你养成翻译的习惯,我猜一切都还可以。

5 个答案:

答案 0 :(得分:11)

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

  

10.6.10“方法体”:

     

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

reachability 的定义在这里(强调添加):

  

8.1“终点和可达性”:

     

如果执行可能达到语句,则语句为   据说可以到达。相反,如果没有可能性   声明将被执行,声称该声明无法访问。

     

...

     

确定特定语句或结束点是否可达,   编译器根据可达性执行流分析   为每个陈述定义的规则。流量分析考虑在内   控制行为的常量表达式(第7.19节)的值   语句,但非常量表达式的可能值   不被视为

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

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

答案 1 :(得分:10)

来自Eric Lippert's blog

  

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

(博客帖子在switch语句中,但我认为可达性分析器对于if语句来说并不聪明。)

答案 2 :(得分:3)

这只是表示编译器在初始化内容以及将执行哪些行方面的智能限制。

我不时遇到这种情况。但它很少是一个问题。我通常会稍微调整一下代码。

答案 3 :(得分:1)

让我们向后分析代码:

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

问题:代码中返回值的位置是什么?

答案:就在最后一行。

结论:因此代码行(最后一行)应始终返回一个值。

问题:最后一行是否总是返回值?

答案:不,只有当testfalsetrue在第一行设置为bool时,它才会返回值。

结论:正如编译器所说,这个函数在返回{{1}}时永远不会返回值。

答案 4 :(得分:0)

让我直接回答您的问题,而不是详细介绍。

  1. 函数的返回类型指定为 Bool ,因此 函数必须返回True或false
  2. Param 已定义为输入参数,因此其值可以 在编译时无法确定
  3. test 变量的
  4. 值取决于参数,并且按照 步骤2,在编译时无法确定 param 的值,因此在编译时无法确定 test 的值
  5. 因为测试的值不称为编译时间(按照步骤3) 因此,它开始寻找 if(!test)的else /默认根目录,然后 因此会引发错误。

谢谢