【问题标题】:Why Elvis (?.) operator doesn't work with async-await?为什么 Elvis (?.) 运算符不适用于 async-await?
【发布时间】:2016-11-05 08:26:42
【问题描述】:

让我们编写这样的代码(App.xaml.xs 的片段):

public class MethodClass
{
    public async Task Job()
    {
        Debug.WriteLine("Doing some sob");
        await Task.Delay(1);
    }
}

public MethodClass MyClass = null;

protected async override void OnLaunched(LaunchActivatedEventArgs e)
{
    await MyClass?.Job(); // here goes NullreferenceException
    MyClass?.Job(); // works fine - does nothing

为什么 Elvis 运算符不能与 async-await 一起使用?我错过了什么吗?

【问题讨论】:

  • 你确定MyClass?.Job(); // works fine ?它只是什么都不做而不抛出异常
  • 因为你的方法 Job 抛出异常
  • 将 Job 定义为 async 并在方法内等待
  • 我想这是因为你实际上是在写await null
  • 因为 await MyClass?.Job() 将在 await 为空时被消耗。它会抛出异常。

标签: c# windows async-await uwp c#-6.0


【解决方案1】:

await 的翻译方式是首先在等待的对象上调用GetAwaiter()(在您的情况下为Task)。然后它会做一些其他复杂的事情,但这些事情在这里不相关:

await MyClass?.Job();

编译为:

var awaiter = MyClass?.Job().GetAwaiter();
// more code

由于Task.GetAwaiter() 是一个实例方法,并且您使用null Task 调用它,因此您会得到NullReferenceException


出于好奇,可以将await 设为null 等待,只要它的GetAwaiter() 是接受null 的扩展方法:

public class NullAwaitable { }

public static class Extensions
{
    public static TaskAwaiter GetAwaiter(this NullAwaitable _)
        => Task.CompletedTask.GetAwaiter();
}

public class MethodClass
{
    public NullAwaitable Job() => new NullAwaitable();
}

MethodClass MyClass = null;

await MyClass?.Job(); // works fine

【讨论】:

  • 感谢您的详细回答,因为我现在想到了我的问题 - 这似乎是一个愚蠢的问题。我想我必须更深入地研究等待者和一些文档。
猜你喜欢
  • 2018-03-24
  • 1970-01-01
  • 2019-10-24
  • 2018-07-10
  • 2021-06-18
  • 2019-05-30
  • 2021-05-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多