我有这段代码:
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);
答案 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;
}