空传播运算符,输出参数和错误的编译器错误?

假设我有一个具有Dictionary类型属性的类,它可以为null。

这会编译但是对TryGetValue()的调用可能会在运行时抛出NullRefexception:

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

所以我添加了一个空传播运算符来防范空值,但这不会编译:

 MyClass c = ...; string val; if( c.PossiblyNullDictionary ?. TryGetValue("someKey", out val) ?? false ) { Console.WriteLine(val); // use of unassigned local variable } 

是否有一个实际的用例,其中val将在if块中未初始化,或者编译器是否根本不能推断出这个(以及为什么)?

更新:最干净的(?)解决方法^ H ^ H ^ H ^ H ^ H修复此问题:

 MyClass c = ...; string val = null; //POW! initialized. if( c.PossiblyNullDictionary ?. TryGetValue("someKey", out val) ?? false ) { Console.WriteLine(val); // no more compiler error } 

通过将val初始化为erhm,value(例如, String.Empty ),编译器能够理解null运算符的意图并按预期运行(通过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 PossiblyNullDictionary; } // Define other methods and classes here 

Ed:通过’grok the intent’我的意思是编译器不能对程序的特性做出重要保证,如果它允许执行将当前作用域保留为未初始化的val 。 当它评估null运算符时,方法调用。

你要求的用例是这样的: bool SomeMethod(string s, out v) TryGetValue,我们有bool SomeMethod(string s, out v) 。 让我们说,当被调用时, SomeMethod是顽皮的,只是有一个return true;的体return true; 。 编译器将方法调用主体视为不透明(因为它可能并不总是在编译器可用/可见的程序集中),因此它得出结论,无法certificateval已初始化。

ed:在回复一些评论时,我想更新我的回答,指出这种行为并不是特定的?? 还是?. C#语言function; 只需使用三元表达式即可重现相同的效果:

 c.PossiblyNullDictionary == null ? false : c.PossiblyNullDictionary.TryGetValue("someKey", out val) //error: use of possibly uninitialized local variable 

好像你遇到了编译器理解的限制?.?? 这并不太令人惊讶,因为它们并没有真正完全融入语言。

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

 MyClass c = new MyClass(); string val; if (c.PossiblyNullDictionary != null && c.PossiblyNullDictionary.TryGetValue("someKey", out val)) { Console.WriteLine(val); // now okay } 

那是因为如果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) { }