如何从基类实现派生类单例?消除重复代码方案
解决C#管理器类重复单例逻辑的问题
可以通过双重泛型基类+Lazy
改进后的基类实现
public abstract class EntityManager<TEntity, TManager> where TManager : EntityManager<TEntity, TManager>, new() { // 用Lazy<T>实现线程安全的懒加载单例 protected static readonly Lazy<TManager> _instance = new Lazy<TManager>(() => new TManager()); public static TManager Instance => _instance.Value; protected List<TEntity> _entities; public IReadOnlyList<TEntity> Entities => _entities; // 保护构造函数,防止外部直接实例化 protected EntityManager() { _entities = new List<TEntity>(); } }
简化后的派生类
现在新增管理器类时,只需继承基类并指定泛型参数,无需再写重复的单例代码:
public sealed class BuildingManager : EntityManager<Building, BuildingManager> { // 这里不需要任何单例相关代码,逻辑全部由基类处理 } public sealed class WallManager : EntityManager<Wall, WallManager> { // 同样无需重复编写单例逻辑 }
关键细节说明
- 双重泛型约束:
where TManager : EntityManager<TEntity, TManager>, new()确保了:- TManager必须是当前基类的派生类
- TManager拥有公共无参构造函数,基类可以通过
new TManager()创建实例
- Lazy
的优势 :比你原来的_instance ?? new()更安全,天然支持线程安全的懒加载,避免多线程环境下创建多个实例的问题 - 类型安全:基类的
Instance属性直接返回具体的管理器类型(如BuildingManager),无需强制转换
替代方案(反射实现)
如果某些管理器无法满足new()约束(比如构造函数有参数),可以用反射在基类中创建实例,但这种方式有轻微性能开销,仅作为备选:
public abstract class EntityManager<TEntity> { private static readonly Lazy<object> _instance = new Lazy<object>(() => Activator.CreateInstance(typeof(EntityManager<TEntity>).Assembly.GetTypes() .First(t => t.IsSubclassOf(typeof(EntityManager<TEntity>)) && t.IsSealed))); public static TManager Instance<TManager>() where TManager : EntityManager<TEntity> { return (TManager)_instance.Value; } protected List<TEntity> _entities; public IReadOnlyList<TEntity> Entities => _entities; protected EntityManager() { _entities = new List<TEntity>(); } }
使用时:
var buildingManager = EntityManager<Building>.Instance<BuildingManager>();
不过这种方式不如双重泛型方案直观,推荐优先使用第一种方案。
内容的提问来源于stack exchange,提问作者WDUK
相关产品推荐
相关产品推荐

