带有空条件运算符和等待的C#错误

Use*_*123 16 c# nullreferenceexception null-conditional-operator

我在C#中使用新的空条件运算符时遇到了一个有趣的System.NullReferenceException.如果"MyObject"为null,则以下代码为我提供NullReferenceException:

await this.MyObject?.MyMethod()
Run Code Online (Sandbox Code Playgroud)

我希望如果"MyObject"为空,或者我误解了空条件运算符的用途,就不会调用"MyMethod"?

M.k*_*ary 21

您可以添加??运算符,如果?.返回null任务,则使用CompletedTask.

await (this.MyObject?.MyMethod() ?? Task.CompletedTask)
Run Code Online (Sandbox Code Playgroud)

我希望如果"MyObject"为空,就不会调用"MyMethod".

确实如此.该?.运营商返回null任务,而不是调用MyMethod.由于您无法等待null任务,因此会生成null引用异常.任务必须初始化.

  • 我知道这已经很老了,但我想提一下,如果 `MyMethod()` 返回一些东西,你也可以做 `var output = wait (this.MyObject?.MyMethod() ?? Task. FromResult(默认(T)));` (7认同)

Sid*_*dex 5

很多讨论都围绕着 await 中空条件的尴尬进行。您可以在 C# 提案Champion "Null-conditional await" #35 中看到其中的一些内容。虽然接受的答案有效,但我相信两种扩展方法更好地封装了行为:

public static Task ForAwait(this Task task)
{
    return task ?? Task.CompletedTask;
}

public static Task<T> ForAwait<T>(this Task<T> task, T defaultValue = default)
{
    return task ?? Task.FromResult(defaultValue);
}
Run Code Online (Sandbox Code Playgroud)

你会使用它们为:await (this.MyObject?.MyMethod()).ForAwait()注意额外的括号!您甚至可以指定自己的默认值,如果 default(T) 不是您想要默认返回的值。我见过其他人做了类似的事情,并在方法中添加了一个额外的参数来配置等待。

我很想摆脱丑陋的括号,不知何故,但语言不允许(还?)。