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
相关产品推荐
相关产品推荐

