11

Let's assume I have a class that has a property of type Dictionary<string,string>, that may be null.

This compiles but the call to TryGetValue() could throw at a NullRef exception at runtime:

MyClass c = ...;
string val;
if(c.PossiblyNullDictionary.TryGetValue("someKey", out val)) {
    Console.WriteLine(val);
}

So I'm adding a null-propagating operator to guard against nulls, but this doesn't compile:

MyClass c = ...;
string val;
if( c.PossiblyNullDictionary ?. TryGetValue("someKey", out val) ?? false ) {

    Console.WriteLine(val); // use of unassigned local variable

}

Is there an actual use case where val will be uninitialized inside the if block, or can the compiler simply not infer this (and why) ?

Update: The cleanest (?) way to workaround^H^H^H^H^H fix this is:

MyClass c = ...;
string val = null; //POW! initialized.
if( c.PossiblyNullDictionary ?. TryGetValue("someKey", out val) ?? false ) {

    Console.WriteLine(val); // no more compiler error

}
4

3 回答 3

5

似乎您遇到了编译器理解的限制,?.??并不奇怪,因为它们并没有真正完全整合到语言中。

如果您在没有较新的运算符的情况下使您的测试显式,编译器将同意您的看法:

MyClass c = new MyClass();
string val;
if (c.PossiblyNullDictionary != null && c.PossiblyNullDictionary.TryGetValue("someKey", out val)) {
    Console.WriteLine(val); // now okay
}
于 2017-12-06T23:08:01.450 回答
3

通过初始化val一个 erhm 值(例如String.Empty),编译器能够理解空运算符的意图并按预期运行(通过 LINQPad,natch):

void Main()
{
    MyClass c = new MyClass();
    string val = string.Empty;
    if (c.PossiblyNullDictionary?.TryGetValue("someKey", out val) ?? false)
    {

        Console.WriteLine(val);

    }
}
public class MyClass {
    public Dictionary<string, string> PossiblyNullDictionary;
}
// Define other methods and classes here

valEd:“理解意图”的意思是,如果编译器允许执行离开未初始化的当前范围,则编译器无法对程序的特征做出重要保证。当它评估空运算符时,方法调用。

您要求的用例是这样的:假设我们有bool SomeMethod(string s, out v). 假设当被调用时,SomeMethod它是顽皮的并且只是有一个return true;. 编译器将方法调用主体视为不透明的(因为它可能并不总是在编译器可用/可见的程序集中),因此它得出结论,没有办法证明它val曾经被初始化。

ed:针对一些评论,我想更新我的答案,指出这种行为并非特定于C#???.C# 语言功能;您只需使用三元表达式即可重现相同的效果:

c.PossiblyNullDictionary == null ? 
    false : 
    c.PossiblyNullDictionary.TryGetValue("someKey", out val) 
 //error: use of possibly uninitialized local variable
于 2017-12-06T23:15:20.003 回答
-3

这是因为如果 c.PossiblyNullDictionary 为 null,则不会执行 TryGetValue,并且该表达式不会返回 true 或 false。

c.PossiblyNullDictionary ?。TryGetValue("someKey", out val) 返回 Nullable,你可以用这样的代码替换你的代码并编译:

        string val;
        var result = c.PossiblyNullDictionary?.TryGetValue("key", out val);
        if (result.HasValue && result.Value)
        {

        }
于 2017-12-06T23:03:33.857 回答