You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何适配Task<T>实现协变接口且不丢失async/await语法支持?

完整实现方案

你猜测的没错,.NET 原生已经提供了AsyncTaskMethodBuilder<T>类型,我们直接将JobBuilder<T>的所有逻辑委托给该类型即可,完全复用原生Task<T>的所有行为逻辑,不需要自己重新实现异步状态机调度。

第一步:修正接口定义(修复笔误)

using System.Runtime.CompilerServices;

[AsyncMethodBuilder(typeof(JobBuilder<>))]
public interface IAsyncJob<out T>
{
    IAwaiter<T> GetAwaiter();
}

public interface IAwaiter<out T> : ICriticalNotifyCompletion
{
    bool IsCompleted { get; }
    T GetResult();
}

第二步:实现Awaiter和Job包装类

// 值类型避免额外堆分配,性能开销几乎可以忽略
public struct Awaiter<T> : IAwaiter<T>
{
    private readonly TaskAwaiter<T> _origin;

    public Awaiter(TaskAwaiter<T> origin) => _origin = origin;

    public bool IsCompleted => _origin.IsCompleted;
    public T GetResult() => _origin.GetResult();
    public void OnCompleted(Action continuation) => _origin.OnCompleted(continuation);
    public void UnsafeOnCompleted(Action continuation) => _origin.UnsafeOnCompleted(continuation);
}

public struct Job<T> : IAsyncJob<T>
{
    private readonly Task<T> _task;

    public Job(Task<T> task) => _task = task;

    public IAwaiter<T> GetAwaiter() => new Awaiter<T>(_task.GetAwaiter());
    
    // 可选:加个隐式转换方便用
    public static implicit operator Job<T>(Task<T> task) => new(task);
}

第三步:完整实现JobBuilder

public class JobBuilder<T>
{
    // 直接委托原生Task构建器,100%复用原生行为
    private readonly AsyncTaskMethodBuilder<T> _nativeBuilder = AsyncTaskMethodBuilder<T>.Create();

    public static JobBuilder<T> Create() => new();

    public void Start<TStateMachine>(ref TStateMachine stateMachine)
        where TStateMachine : IAsyncStateMachine
        => _nativeBuilder.Start(ref stateMachine);

    public void SetStateMachine(IAsyncStateMachine stateMachine)
        => _nativeBuilder.SetStateMachine(stateMachine);

    public void SetResult(T result)
        => _nativeBuilder.SetResult(result);

    public void SetException(Exception exception)
        => _nativeBuilder.SetException(exception);

    public IAsyncJob<T> Task => new Job<T>(_nativeBuilder.Task);

    public void AwaitOnCompleted<TAwaiter, TStateMachine>(
        ref TAwaiter awaiter, ref TStateMachine stateMachine)
        where TAwaiter : INotifyCompletion
        where TStateMachine : IAsyncStateMachine
        => _nativeBuilder.AwaitOnCompleted(ref awaiter, ref stateMachine);

    public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(
        ref TAwaiter awaiter, ref TStateMachine stateMachine)
        where TAwaiter : ICriticalNotifyCompletion
        where TStateMachine : IAsyncStateMachine
        => _nativeBuilder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
}

第四步:可选扩展方法(方便转换)

public static class AsyncJobExtensions
{
    public static IAsyncJob<T> ToAsyncJob<T>(this Task<T> task) => new Job<T>(task);
}

功能验证

所有原生Task<T>支持的行为(异常传播、取消处理、同步上下文调度等)都可以正常使用,同时完全满足协变需求:

class A {}
class B : A {}

// async返回IAsyncJob<T>完全正常
async IAsyncJob<B> GetBAsync()
{
    await Task.Delay(100);
    return new B();
}

// 协变场景
IAsyncJob<B> bJob = GetBAsync();
IAsyncJob<A> aJob = bJob;
A result = await aJob;

// 接口层级协变也完全支持
public interface IJobAsyncGetter<out T>
{
    IAsyncJob<T> GetAsync();
}
IEnumerable<IJobAsyncGetter<B>> bList = Enumerable.Empty<IJobAsyncGetter<B>>();
IEnumerable<IJobAsyncGetter<A>> aList = bList; // 编译完全通过

内容的提问来源于stack exchange,提问作者Valentyn Zakharenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 16:57:04