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

C#中Action<A>与Action<B>(B继承A)的合法转换方式咨询

解决方案

为什么直接转换会失败

Action<B>不能直接强制转换为Action<A>,这是因为委托的逆变特性有严格限制:虽然Action<T>是逆变类型,但C#不允许直接对已有的Action<TDerived>实例做显式强制转换,必须通过安全的委托包装或类型转换机制实现。

更优雅的实现方式

方式1:用Delegate.CreateDelegate实现零开销转换

这种方法直接复用原委托的目标对象和方法,没有额外lambda包装的性能开销:

public void Execute()
{
    var convertedCallback = (Action<A>)Delegate.CreateDelegate(typeof(Action<A>), _callback.Target, _callback.Method);
    onCompleted += convertedCallback;
    // doing something specific.
}

方式2:封装泛型扩展方法提升复用性

如果需要在多个场景做类似转换,可以封装通用扩展方法,让代码更简洁易读:

public static class DelegateExtensions
{
    public static Action<TBase> ToBaseAction<TDerived, TBase>(this Action<TDerived> action) 
        where TDerived : TBase
    {
        return arg => action((TDerived)arg);
    }
}

在B类中调用:

public void Execute()
{
    onCompleted += _callback.ToBaseAction<B, A>();
    // doing something specific.
}

方式3:调整基类设计,从根源避免转换

如果可以修改抽象类A的结构,改用泛型基类的方式,彻底消除委托转换的需求:

public abstract class A<T> where T : A<T>
{
    protected event Action<T> onCompleted;

    public void CompleteExecution()
    {
        onCompleted?.Invoke((T)this);
    }
}

public class B : A<B>
{
    private Action<B> _callback;

    public void Initialize(Action<B> callback)
    {
        _callback = callback;
    }

    public void Execute()
    {
        onCompleted += _callback;
        // doing something specific.
    }
}

这种设计类型安全,代码最简洁,是最优的长期解决方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 13:47:44