是否可以在基类上有虚拟异步方法

本文关键字:虚拟 异步方法 基类 是否 | 更新日期: 2023-09-27 18:15:30

我正在处理一些代码,其中我有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
   }
}

类似(但不相同)的问题已经问过了。

是否可以在基类上有虚拟异步方法

简短回答

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

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

长回答

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

protected virtual Task LoadDataAsync() {
  return Task.CompletedTask;
}

实现中的关键更改如下:

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

是的,这很好,但你应该使用async Task而不是async void。我有一篇MSDN文章解释了为什么

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

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