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

时间:2014-07-29 12:56:27

标签: 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
   }
}

Similar (but not same)问题已被提出。

3 个答案:

答案 0 :(得分:67)

简短回答

  • virtual方法可以标记为async
  • abstract方法无法标记为async

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

答案很长

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

protected virtual Task LoadDataAsync() {
  return Task.FromResult(default(object));
}

您的实施的主要变化如下:

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

答案 1 :(得分:19)

是的,没关系,但您应该使用async Task代替async void。我有MSDN article that explains why

答案 2 :(得分:-4)

同意@Sam。
我抛出异常只是为了确保实现实际的逻辑。更符合我的要求,就是这样。

protected virtual Task LoadDataAsync()
{
    throw new NotImplementedException();
}