未分配的局部变量和短路评估

时间:2017-01-19 13:45:46

标签: c#

我有两种方法,它们都能正确编译:

public int A()
{
    int i;
    if(!int.TryParse("0", out i))
    {
        return -1;
    }
    // do sth
    return i;
}

public int B()
{
    int i;
    if(true)
    {
        return -1;
    }
    return i;
}

在第二种情况下(方法B),编译器足够聪明,可以检测到从未使用过变量i,所以它不会抱怨没有分配它。

但是,我有另一个例子(两者的组合)似乎等同于方法B

public int C()
{
    int i;
    if (true || !int.TryParse("0", out i))
    {
        return -1;
    }
    return i;
}

VisualStudio 2012 .NET Framework 4.6.01055 )下的Windows上进行编译时,会抛出错误:Use of unassigned local variable 'i'。解决方案是:

  • 使用任何值初始化i
  • 使用|运算符代替||

为什么会这样?看起来编译器具有检测无法访问代码的所有必要数据。

旁注:示例C mono 4.6.2 下的 Linux 上编译,并显示有关无法访问的代码的警告。< / p>

2 个答案:

答案 0 :(得分:1)

这不能被视为一个错误,但它是一个可以改进的功能。当你说编译器有足够的信息知道从未使用过未分配的i时,你是正确的,因此它应该省略编译器错误。

它的可以改进,因为事实上它已得到改善;在VS 2015中,编译器的行为是预期的:没有编译时错误。我不能对以前版本的编译器说同样的话,因为我现在无法对它们进行测试。

有趣的是,VS 2015或VS 2017 RC都没有在return i报告无法访问的代码警告,这似乎有点奇怪。 if (true)会正确地提供此警告和if (true || ....)数字i未被使用,但由于我不理解的原因而忽略了警告。

有关行为更改原因的更多信息,请查看此one。我知道这个问题响了一个钟......我几年前曾问过类似的问题;)。

答案 1 :(得分:0)

  

在Visual Studio 2012(.NET Framework 4.6.01055)下的Windows上进行编译时,会抛出错误:使用未分配的局部变量“i”

应该如此。该变量未分配。您可能不会在代码中引用它。有时候,根据编译器的不同,它可能事先知道该行永远不会执行,并在检查变量使用之前完全删除它。其他版本可能会切换可能导致不同结果的步骤。我个人会说你不应该依赖它:代码安全。

仅供参考。 Roslyn(最新的.NET编译器)在编译时不会出错。似乎验证只会丢弃所有||条件。

if (true || !int.TryParse("0", out i)) // // does not give an error, first return always used, other discarded

if (true && !int.TryParse("0", out i)) // does not give an error, i is known to always be assigned

if (false && !int.TryParse("0", out i)) // gives an error, if never results in true, and parse is known not to be called