在基类上使用虚拟异步方法是否可以?

Sam*_*yan 43 c# asynchronous async-await c#-5.0

我正在使用一些代码,我有2个类,逻辑和代码非常相似.我protected async void LoadDataAsync()在这两个课上都有方法.
目前我正在重构它并考虑将共享逻辑移动到基类.
是否可以virtual async在基类上使用方法并在派生类上覆盖它?
它有什么问题吗?
我的代码看起来像这样:

public class Base
{
   protected virtual async void LoadDataAsync() {}
}

public class Derived : Base
{
   protected override async void LoadDataAsync()
   {
       // awaiting something
   }
}
Run Code Online (Sandbox Code Playgroud)

已经提出类似(但不相同)的问题.

Sam*_*ell 72

简短的回答

  • virtual方法可以被标记为async
  • abstract方法不能被标记为async

这样做的原因async实际上并不是方法签名的一部分.它只是告诉编译器如何处理方法体本身的编译(并不适用于重写方法).由于抽象方法没有方法体,因此应用async修改器没有意义.

答案很长

如果基类提供了方法的默认实现但不需要做任何工作,我建议使用以下代码,而不是基类中的当前签名.

protected virtual Task LoadDataAsync() {
  return Task.FromResult(default(object));
}
Run Code Online (Sandbox Code Playgroud)

您实施的主要变化如下:

  1. 将返回值更改voidTask(记住async实际上不是返回类型的一部分).与返回不同void,当Task返回a时,调用代码可以执行以下任何操作:
    • 等待操作完成
    • 检查任务的状态(已完成,已取消,出现故障)
  2. 避免使用async修饰符,因为该方法不需要await任何操作.相反,只需返回已完成的Task实例.重写此方法的方法仍然可以在async需要时使用修饰符.

  • 也许Task.CompletedTask应该更好? (5认同)

Ste*_*ary 19

是的,没关系,但你应该用async Task而不是async void.我有一篇MSDN文章解释了原因.