在 C# 中使用新的空条件运算符时,我遇到了一个有趣的 System.NullReferenceException。如果“MyObject”为空,下面的代码会给我一个 NullReferenceException:
await this.MyObject?.MyMethod()
我原以为如果“MyObject”为空,则根本不会调用“MyMethod”,还是我误解了空条件运算符的目的?
在 C# 中使用新的空条件运算符时,我遇到了一个有趣的 System.NullReferenceException。如果“MyObject”为空,下面的代码会给我一个 NullReferenceException:
await this.MyObject?.MyMethod()
我原以为如果“MyObject”为空,则根本不会调用“MyMethod”,还是我误解了空条件运算符的目的?
您可以添加??
运算符,因此如果?.
返回 null 任务,请改用 CompletedTask。
await (this.MyObject?.MyMethod() ?? Task.CompletedTask)
我原以为如果“MyObject”为空,则根本不会调用“MyMethod”。
确实如此。运算符?.
返回 null 任务而不是调用MyMethod
. 产生空引用异常是因为您不能等待空任务。必须初始化任务。
围绕等待中空条件的尴尬进行了很多讨论。您可以在 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);
}
您可以将它们用作:await (this.MyObject?.MyMethod()).ForAwait()
. 注意额外的括号!如果 default(T) 不是您想要默认返回的值,您甚至可以指定您自己的默认值。我见过其他人做类似的事情,并在方法中添加了一个额外的参数来配置等待。
不知何故,我很想摆脱丑陋的括号,但是语言不允许这样做(还没有?)。