【问题标题】:C# Error with null-conditional operator and await带有空条件运算符和等待的 C# 错误
【发布时间】:2016-02-09 02:53:18
【问题描述】:

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

await this.MyObject?.MyMethod()

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

【问题讨论】:

    标签: c# nullreferenceexception null-conditional-operator


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 我知道这已经很老了,但我想提醒一下,如果MyMethod() 返回了一些东西,你也可以这样做var output = await (this.MyObject?.MyMethod() ?? Task.FromResult(default(T)));
    【解决方案2】:

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

    我很想以某种方式摆脱丑陋的括号,但语言不允许这样做(现在?)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-11
      • 2013-08-14
      • 1970-01-01
      • 2017-12-01
      • 2012-03-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多