38

在 C# 中使用新的空条件运算符时,我遇到了一个有趣的 System.NullReferenceException。如果“MyObject”为空,下面的代码会给我一个 NullReferenceException:

await this.MyObject?.MyMethod()

我原以为如果“MyObject”为空,则根本不会调用“MyMethod”,还是我误解了空条件运算符的目的?

4

2 回答 2

55

您可以添加??运算符,因此如果?.返回 null 任务,请改用 CompletedTask。

await (this.MyObject?.MyMethod() ?? Task.CompletedTask)

我原以为如果“MyObject”为空,则根本不会调用“MyMethod”。

确实如此。运算符?.返回 null 任务而不是调用MyMethod. 产生空引用异常是因为您不能等待空任务。必须初始化任务。

于 2015-11-08T09:35:29.230 回答
9

围绕等待中空条件的尴尬进行了很多讨论。您可以在 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) 不是您想要默认返回的值,您甚至可以指定您自己的默认值。我见过其他人做类似的事情,并在方法中添加了一个额外的参数来配置等待。

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

于 2020-12-24T08:07:05.073 回答