我刚遇到一个案例,其中Visual Studio告诉我我的代码可能会导致访问未初始化的变量,但是布尔逻辑规则规定这在这里是不可能的。
我简化了代码以可视化问题,在这种情况下,该问题出现在x
上:
static void Main(string[] args)
{
IDictionary<String, MyType> dictionary = null;
if (new Random().Next() % 2 == 0)
{
dictionary = new Dictionary<string, MyType>();
dictionary.Add("xyz", MyType.Whatever);
dictionary.Add("abc", MyType.DontCare);
}
var myType = dictionary?.TryGetValue("abc", out var x) ?? false ? x : MyType.None;
}
enum MyType
{
None,
Whatever,
DontCare
}
如果dictionary
未初始化,则它为null,从而导致??
将三元运算符评估为false
。这是唯一不会初始化x
的情况,但是在三元运算符的真实情况下,我仍然收到x
的错误消息。
备注:设置括号不会更改任何内容,如果也没有,则将三元运算符解析为完整的功能。
这是已知行为还是错误?
编辑:只是为了澄清,我确实知道如何解决该问题。遇到此错误令我有些惊讶,因为根据布尔逻辑,描述的问题(访问未初始化的x
)将永远不会发生。
编辑:如果使用完整则不会改变问题:
static void Main(string[] args)
{
...
MyType myType;
if (dictionary?.TryGetValue("abc", out var x) ?? false)
{
myType = x; // <-- error still occurs here
}
else
{
myType = MyType.None;
}
}
答案 0 :(得分:2)
问题是此行中的x
:
var myType = dictionary?.TryGetValue("abc", out var x) ?? false ? x : MyType.None;
由于您具有null传播运算符(?.
),因此,x
为dictionary
时将不会分配null
。您必须将x
作为var
上方的一个独立变量,并使用默认值。
MyType x = MyType.None;
var myType = dictionary?.TryGetValue("abc", out x) ?? false ? x : MyType.None;
静态编译器不够聪明,无法弄清楚null传播运算符将导致该表达式始终返回false(因此,从未使用x
)。不仅如此,它只是尽可能地对待该语句。
正如您在C#语言Github页面上所看到的,有一个active feature request让编译器找出空传播运算符的结果。