本地变量可能在访问之前未初始化-调用.TryParse()之后

时间:2019-01-09 10:14:00

标签: c# .net-core

我有这段代码:

var kv = new Dictionary<int, string>() { ... };

var kv30Valid = kv.ContainsKey(30) && int.TryParse(kv[30], out var kv30Value);

myObject.nullableInt = kv30Valid ? (int?)kv30Value : null;

注意:myObject是代表表行的POCO类,这就是可为null的int的原因。

我无法编译代码,因为在最后一行出现编译器错误:

  

访问之前,本地变量'kv30Value'可能未初始化

在哪种情况下可以将其取消初始化,以及如何正确处理该情况以允许有效代码?

我需要用kv的值(如果存在)填充myObject属性,这些值将解析为各自的值。

解决方案: 将条件移至TryParse()方法即可解决此问题。

var kv30Valid = int.TryParse(kv.ContainsKey(30) ? kv[30] : null, out var kv30Value);

2 个答案:

答案 0 :(得分:4)

定值分析器有局限性(必须解决,yada yada yada暂停问题等)。尽管我们可以看一下这段代码并得出结论,只有在kv30value返回true并因此调用了ContainsKey时,它才会访问TryParse,但对于分析器来说,它太“独立”了看到这个。

如果该文件位于使用if的{​​{1}}块中,则可能可以看到它,但是即使那样我也不确定。

答案 1 :(得分:0)

  

在哪种情况下可以取消初始化

kv.ContainsKey(30)返回false时,不会调用int.TryParse(),也不会分配kv30Value

为简化问题,您有一个未分配的变量:

bool test; // declared, but not assigned
if (test)
{
    Console.WriteLine("Test is true");
}

这将不会编译,因为未分配test

现在,带有out参数的方法肯定会分配变量:

bool test;
Assign(out test);

if (test)
{
    Console.WriteLine("Test is true");
}

private static void Assign(out bool foo)
{
    foo = true;
}

这将打印“ Test is true”。

现在,如果您将分配作为条件:

bool test;

bool condition = DateTime.Now > DateTime.Now;
if (condition)
{
    Assign(out test);
}

if (test) { ... }

您会回到编译器错误中

  

CS0165:使用未分配的局部变量test

由于编译器无法保证test的分配,因此它禁止进一步使用该变量。

即使变量的用法使用相同的条件:

bool test;

bool condition = DateTime.Now > DateTime.Now;
if (condition)
{
    Assign(out test);
}

if (condition && test)
{
    Console.WriteLine("Test is true");
}

然后编译器仍然拒绝您使用test

与您的&& int.TryParse(..., out)代码完全相同。 &&的右侧是有条件执行的,因此编译器将拒绝让您使用可能未分配的变量。

关于下面的讨论和对我的回答的否定,如果您想了解所有这些内容背后的原因,请参阅C#语言规范第5.3章明确分配。基本上说,您会收到此错误,因为编译器会尽最大努力尝试静态分析变量是否已分配。

  

如何正确处理案件以允许有效代码?

在上面进行声明,并为其指定一个合理的默认值:

int kv30Value = 0;
var kv30Valid = kv.ContainsKey(30) && int.TryParse(kv[30], out kv30Value);

或者通过将代码移到if中来简化代码,在此位置将明确分配代码:

if (kv.ContainsKey(30) && int.TryParse(kv[30], out var kv30Value))
{
    myObject.nullableInt = kv30Value;
}