C#中将派生泛型类作为派生类属性是否属于反模式?
解决方案
你要的效果可以通过**奇异递归模板模式(CRTP)**实现,这是C#中处理这类派生类与配套泛型类型绑定场景的标准方案,不属于反模式,也不需要更换整体设计思路。
第一步:修正接口定义
首先你现有代码存在两处笔误和可优化点:
- 两个参数类命名重复,第二个
ObjectTypeA应为ObjectTypeB IObjectType<in T>的Foo方法参数没有用到泛型约束,浪费了逆变的类型安全能力,修正后代码如下:
// 业务对象基类,非泛型版本用于统一存储、传递 public abstract class BaseObject { // 可放置所有业务对象共有的非泛型属性、方法 } public interface IObjectType<in T> where T : BaseObject { // 参数用泛型约束的T,替代原来的BaseObject,保证类型安全 void Foo(T obj); } // 对应ObjectA的参数类 public class ObjectTypeA : IObjectType<ObjectA> { public void Foo(ObjectA obj) { // ObjectA专属配置逻辑 } } // 对应ObjectB的参数类 public class ObjectTypeB : IObjectType<ObjectB> { public void Foo(ObjectB obj) { // ObjectB专属配置逻辑 } }
第二步:用CRTP定义泛型业务基类
给BaseObject增加泛型重载,约束泛型参数必须是当前派生类本身,直接在基层完成IObjectType属性的绑定:
public abstract class BaseObject<TSelf> : BaseObject where TSelf : BaseObject<TSelf> { public IObjectType<TSelf> Type { get; private set; } public void SetType(IObjectType<TSelf> type) { Type = type; } }
第三步:实现派生业务类
派生类只需要将自身作为泛型参数传入基类,即可自动获得对应类型的IObjectType属性,不需要重复编写属性、方法定义:
public class ObjectA : BaseObject<ObjectA> { // 自动继承的Type属性为IObjectType<ObjectA>类型 // 自动继承的SetType方法仅接受IObjectType<ObjectA>参数 } public class ObjectB : BaseObject<ObjectB> { // 自动继承的Type属性为IObjectType<ObjectB>类型 // 自动继承的SetType方法仅接受IObjectType<ObjectB>参数 }
效果验证
var objA = new ObjectA(); objA.SetType(new ObjectTypeA()); // 编译通过,类型匹配 objA.SetType(new ObjectTypeB()); // 编译报错,类型不匹配,符合预期的类型约束 objA.Type.Foo(objA); // 直接调用Foo方法,不需要任何类型转换
如果你需要统一存放不同类型的业务对象,直接使用非泛型BaseObject作为集合元素类型即可:
List<BaseObject> allObjects = new List<BaseObject>(); allObjects.Add(objA); allObjects.Add(new ObjectB());
内容的提问来源于stack exchange,提问作者Julzerino Szach
相关产品推荐
相关产品推荐

