为什么 Elvis (?.) 运算符不适用于异步等待?
Why Elvis (?.) operator doesn't work with async-await?
让我们有这样的代码(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 一起使用?我错过了什么吗?
await
的翻译方式是,首先对等待的对象(在您的情况下是 Task
)调用 GetAwaiter()
。然后它会做一些其他复杂的事情,但这些与这里无关:
await MyClass?.Job();
编译为:
var awaiter = MyClass?.Job().GetAwaiter();
// more code
由于 Task.GetAwaiter()
是一个实例方法并且您使用 null
Task
调用它,您将得到 NullReferenceException
.
出于好奇,可以 await
等待 null
,只要它的 GetAwaiter()
是接受 null
:[=24 的扩展方法=]
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
让我们有这样的代码(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 一起使用?我错过了什么吗?
await
的翻译方式是,首先对等待的对象(在您的情况下是 Task
)调用 GetAwaiter()
。然后它会做一些其他复杂的事情,但这些与这里无关:
await MyClass?.Job();
编译为:
var awaiter = MyClass?.Job().GetAwaiter();
// more code
由于 Task.GetAwaiter()
是一个实例方法并且您使用 null
Task
调用它,您将得到 NullReferenceException
.
出于好奇,可以 await
等待 null
,只要它的 GetAwaiter()
是接受 null
:[=24 的扩展方法=]
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