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

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

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

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

10.6.10“方法体”:

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

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

8.1“终点和可达性”:

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

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

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

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

来自Eric Lippert的博客 :

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

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

这只是表示编译器在初始化内容和执行哪些行方面的智能程度的局限性。

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

让我们向后分析代码:

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

问题:在代码中返回值的位置?

答:就在最后一行。

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

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

答案:不,如果test在第一行设置为true ,则只返回false

结论:正如编译器所说,这个函数永远不会返回一个值,而它应该返回bool

让我直接回答你的问题,而不是详细说明。

  1. 返回类型的函数被指定为Bool,因此该函数必须返回True或false
  2. Param已被定义为输入参数,因此无法在编译时确定其值
  3. 测试变量的值取决于参数,并且按照步骤2,在编译时无法确定参数值,因此在编译时无法确定测试
  4. 由于test的值不称为编译时间(按照步骤3),因此它开始为if(!test)寻找else / default root,因此它会抛出错误。

谢谢