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

C#:运行时未知具体类型时转换多态对象至特定子类型

运行时泛型Holder类型转换优化方案

核心需求

将非泛型Holder父类实例,在运行时转换为其实际对应的泛型子类Holder<T>,避免手动添加类型分支或创建大量冗余子类,同时适配Unity C#环境(无法使用dynamic)。


方案1:反射封装扩展方法(无侵入改造)

无需修改原有Holder和SomeNode结构,通过封装反射逻辑实现通用值访问:

public static class HolderExtensions
{
    // 强类型获取值(已知目标类型时使用)
    public static T GetValue<T>(this Holder holder)
    {
        // 先尝试直接类型转换
        if (holder is Holder<T> typedHolder)
        {
            return typedHolder.Value;
        }
        // 运行时反射匹配类型
        var valueProperty = holder.GetType().GetProperty("Value");
        if (valueProperty != null)
        {
            return (T)valueProperty.GetValue(holder);
        }
        throw new InvalidCastException($"无法将Holder转换为Holder<{typeof(T)}>");
    }

    // 通用获取值(未知目标类型时使用)
    public static object GetValue(this Holder holder)
    {
        var valueProperty = holder.GetType().GetProperty("Value");
        return valueProperty?.GetValue(holder) ?? null;
    }
}

使用示例:

// 已知目标类型的场景
var stringValue = holder.GetValue<string>();
// 未知类型的场景,获取后按需处理
var rawValue = holder.GetValue();
Console.WriteLine(rawValue?.ToString());

方案2:基类添加委托实现纯多态(性能最优)

修改基类Holder,通过泛型委托封装值访问逻辑,完全避免反射开销:

public class Holder
{
    protected Func<object> _getValueDelegate;

    // 通用值访问入口
    public object GetValue() => _getValueDelegate?.Invoke() ?? null;
}

public class Holder<T> : Holder
{
    public T Value;

    public Holder()
    {
        // 初始化委托,绑定泛型Value属性
        _getValueDelegate = () => Value;
    }
}

使用示例:

public class EchoNode : SomeNode
{
    public void Tick()
    {
        Console.WriteLine(holder.GetValue()?.ToString());
    }
}

如果需要强类型访问,可在基类中添加泛型扩展方法,或直接在子类中重写泛型获取逻辑:

public class Holder
{
    protected Func<object> _getValueDelegate;
    public object GetValue() => _getValueDelegate?.Invoke() ?? null;

    public virtual T GetValue<T>() => default;
}

public class Holder<T> : Holder
{
    public T Value;

    public Holder()
    {
        _getValueDelegate = () => Value;
    }

    public override TTarget GetValue<TTarget>()
    {
        if (typeof(TTarget) == typeof(T))
        {
            return (TTarget)(object)Value;
        }
        throw new InvalidCastException("类型不匹配");
    }
}

方案对比

  • 方案1:无侵入式改造,适配现有代码结构,反射开销在Unity非高频调用场景可忽略,适合快速迭代。
  • 方案2:纯多态实现,无反射性能损耗,代码更严谨,适合长期维护的项目,但需要修改基类结构。

两种方案均无需创建FloatHolder这类冗余子类,也不需要手动编写类型分支逻辑,完美适配运行时确定类型的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 20:31:13