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

如何从基类实现派生类单例?消除重复代码方案

解决C#管理器类重复单例逻辑的问题

可以通过双重泛型基类+Lazy线程安全懒加载的方式,彻底消除派生类中的重复单例代码。核心思路是让基类同时约束实体类型和管理器自身类型,利用泛型约束确保能创建管理器实例,同时借助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>
{
    // 同样无需重复编写单例逻辑
}

关键细节说明

  1. 双重泛型约束:where TManager : EntityManager<TEntity, TManager>, new() 确保了:
    • TManager必须是当前基类的派生类
    • TManager拥有公共无参构造函数,基类可以通过new TManager()创建实例
  2. Lazy的优势:比你原来的_instance ?? new()更安全,天然支持线程安全的懒加载,避免多线程环境下创建多个实例的问题
  3. 类型安全:基类的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 17:24:56