我有一个Base类,它提供了一个带有以下签名的方法:
virtual async Task RunAsync()
派生类应该用
之类的方式覆盖此实现public override async Task RunAsync()
{
await base.RunAsync();
await this.DoSomethingElse();
}
现在,编译器向我发出警告,指出Base.RunAsync缺少await语句。我希望我的代码是免费警告,而不是抑制警告,并且它运行而不必提供空检查,即使派生类没有提供覆盖实现,因此使用virtual Task RunAsync()
(省略async关键字)是不可能。
现在基本方法中的实现是await Task.Delay(0);
,它解除了编译器的警告,但在我看来,它在某种程度上并不“干净”。什么是应对这个主题的正确方法?
答案 0 :(得分:14)
你误解了async
的工作原理。它不是签名的一部分,因此,如果您 await
,您实际上不必使用它。因此,即使您提供Task RunAsync()
方法,也可以在不使用 async
的情况下编写,例如:
virtual Task RunAsync()
{
return Task.FromResult(false);
}
这仍然允许您进行实际使用await
的覆盖,如下所示:
override async Task RunAsync()
{
await base.RunAsync();
await DoSomeOtherStuffAsync();
}
这就是编译器为您提供警告的原因 - async
关键字完全没用,而不是方法签名的一部分。它只是向编译器发出的一个信号,它允许使用标识符await
作为关键字,基本上是为了保持与旧C#代码的向后兼容性。
编辑:
正如Jeroen Mostert在评论中所述,从.NET Framework 4.6开始,Task.CompletedTask
属性是公共的,所以你可以这样做:
virtual Task RunAsync()
{
return Task.CompletedTask;
}
因此,如果你可以使用4.6+,这是最新,最干净的选择。当然,如果您需要任务实际返回值,Task.FromResult
仍然存在:)