为什么Elvis(.)运算符不能与async-await一起工作

本文关键字:async-await 一起 工作 不能 运算符 Elvis 为什么 | 更新日期: 2023-09-27 18:16:21

让我们有一个这样的代码(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

为什么猫王操作符不能使用async-await?我错过什么了吗?

为什么Elvis(.)运算符不能与async-await一起工作

翻译await的方式是,首先在等待的对象(在您的示例中是Task)上调用GetAwaiter()。然后它做一些其他复杂的事情,但这些与这里无关:

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