错误:“无法在没有主体的方法上使用'异步'”.如何强制异步子项覆盖

本文关键字:异步 覆盖 何强制 方法 主体 错误 | 更新日期: 2023-09-27 17:58:42

我正在开发一个系统,其中多个客户端对象应通过接口实现特定功能,并且我希望该函数与延续异步运行(我希望实现是I/O绑定的,并希望确保所有客户端对象尽快完成此功能(。 我正在使用Visual Studio Async CTP Refresh for SP1,C#"5.0"。

在我的抽象类的子对象中强制实施异步行为的推荐做法是什么(见下文(? 我不能(显然(使用虚拟方法强制使用"异步"方法。 我只需要一个"任务"返回类型。 这是否意味着我根本不应该尝试在子对象中要求异步行为? 在这种情况下,返回类型是否应该只是"无效"?

公共接口是目前系统设计的不幸后果,但这是一个单独的问题。 显然,我无法限制任何绕过"BaseFoo"而只实现"IFoo"接口的异步人。

这是代码:

public interface IFoo
{
    void Bar(); //NOTE: Cannot use 'async' on methods without bodies.
}
public abstract class BaseFoo : IFoo
{
    public async void Bar()
    {
        await OnBar(); //QUESTION: What is the right "async delegation" pattern?
    }
    protected virtual async Task OnBar()
    {
        await TaskEx.Yield();
    }
}
public class RealFoo : BaseFoo //NOTE: May be implemented by 3rd party
{
    protected override async Task OnBar()
    {
        //CLIENT: Do work, potentially awaiting async calls
        await TaskEx.Yield(); //SECONDARY QUESTION: Is there a way to avoid this if there are no 'awaits' in the client's work?
    }
}

错误:“无法在没有主体的方法上使用'异步'”.如何强制异步子项覆盖

方法是否使用 async/await 实现是一个实现细节。该方法的行为方式是一个合同细节,应该以正常方式指定。

请注意,如果使方法返回TaskTask<T>,则更明显的是,它应该是异步的,并且如果不异步,可能很难实现。

另一方面,如果有一个实现(例如用于测试目的(,其中await表达式永远不会不完整,你为什么要强迫某人编写一个没有await调用的异步方法呢?您希望实现是IO绑定的,但可能会有特殊情况,实现想要使用硬编码数据等。

基本上,您必须在该方法的文档中处理此问题 - 如果您不能信任实现者阅读它,那么您无论如何都没有机会:(

除了 Jon 的答案之外,如果您遵循基于任务的异步模式,那么您的方法名称应该带有后缀 Async ,它自己记录它是一个异步方法。

如果您正在实现接口

public interface IFoo
{
    Task BarAsync();
}

很明显,这应该使用 async 关键字来实现。