首页 > 编程语言 >精简实现、线程安全:C#通用单例泛型基类助你轻松创建单例模式

精简实现、线程安全:C#通用单例泛型基类助你轻松创建单例模式

时间:2024-03-04 09:03:57浏览次数:34  
标签:Lazy C# MySingletonClass 线程 单例 基类 泛型

 

概述:该通用单例泛型基类使用C#实现,线程安全,通过泛型参数和Lazy<T>实现简化的单例模式。优点包括线程安全、泛型通用性、简化实现、以及延迟加载的特性。

优点:

  1. 线程安全: 使用Lazy<T>确保了线程安全的延迟初始化,避免了在多线程环境下可能导致的竞态条件问题。
  2. 泛型通用性: 通过泛型参数,该单例基类适用于任何类,提高了代码的通用性和可重用性,避免了为每个类都实现单例模式的重复劳动。
  3. 简化实现: 泛型和Lazy<T>的使用简化了单例模式的实现。派生类只需继承这个基类,即可获得单例模式的特性,减少了冗余的代码。
  4. 延迟加载: 通过延迟加载的特性,实例在第一次被请求时才被创建,提高了性能,避免了不必要的资源浪费。

以下是一个线程安全的通用单例泛型基类的C#实现:

using System;

// 泛型单例基类
public class Singleton<T> where T : class
{
    // 使用Lazy<T>确保线程安全的延迟初始化
    private static readonly Lazy<T> instance = new Lazy<T>(() => CreateInstanceOfT(), isThreadSafe: true);

    // 提供获取单例实例的静态属性
    public static T Instance => instance.Value;

    // 保护的构造函数,防止直接实例化
    protected Singleton()
    {
        // 在此处可以添加其他初始化逻辑
    }

    // 创建T类型的实例
    private static T CreateInstanceOfT()
    {
        return Activator.CreateInstance(typeof(T), true) as T;
    }
}

// 示例类
public class MySingletonClass : Singleton<MySingletonClass>
{
    // 在此处可以添加其他成员或方法
    private MySingletonClass()
    {
        // 在此处可以添加初始化逻辑
    }
}

class Program
{
    static void Main()
    {
        // 使用单例实例
        MySingletonClass instance1 = MySingletonClass.Instance;
        MySingletonClass instance2 = MySingletonClass.Instance;

        // 验证是否为同一实例
        Console.WriteLine($"instance1 == instance2: {instance1 == instance2}");

        // 可以在这里添加其他业务逻辑...
    }
}

上面的Singleton<T>为通用型,在没有应用其它容器进行单例注册时这种方法还是比较简单方便的。

 

标签:Lazy,C#,MySingletonClass,线程,单例,基类,泛型
From: https://www.cnblogs.com/hanbing81868164/p/18051099

相关文章

  • C#/.NET/.NET Core优秀项目和框架2024年2月简报
    前言公众号每月定期推广和分享的C#/.NET/.NETCore优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项目和框架源码......
  • ascii码表里 转义字符有哪些
    ASCII码表中的转义字符主要有以下几种:\a:响铃(BEL),对应的ASCII码值是7。\b:退格(BS),对应的ASCII码值是8。它将光标移回前一个字符,但不会删除该字符,只是将光标移回。\f:换页(FF),对应的ASCII码值是12。它用于控制输出设备(如打印机)开始新的页面。\n:换行(LF),对应的ASCII码值是10。它......
  • ElasticSearch入门实战
    全文检索根据搜索条件将相关内容结果进行检索。查询:根据明确的条件对数据进行过滤,例如年龄>20且工资<10000的人进行过略。检索:没有明确的条件,通过相关性将结果进行返回,例如根据查询条件的同义词、错别字等等进行查询。通过常规的模糊查询只能查出包含xxx的内容,而没办......
  • northwest uniapp: 顶部导航栏右侧添加uni-icons图标,并绑定点击事
    说明该配置按页面配置,无法全局配置使用方法引入uni-icons插件插件地址:点击此处跳转到uni-icons引入以后,会发现uni-modules中新增如下目录和文件:仅需要那个uniicons.ttf文件,不引入插件、单独把那个文件下载到本地也是可以的。复制uniicons.ttf文件到static目录下不知道......
  • 【C++ STL容器set 】std::set 的全方位解析
    装载自知乎(虽然有AI辅助操作,但是确实写得好好):【C++STL容器set】std::set的全方位解析-知乎(zhihu.com)<imgsrc="https://pic3.zhimg.com/v2-cc8068b8931c7f65e9a89717e2ab404e_b.jpg"data-size="normal"data-rawwidth="1024"data-rawheight="1024......
  • RUN、CMD、ENTRYPOINT区别
    1、简要概述RUN:执行命令并创建新的镜像层,RUN经常用于安装软件包。CMD:设置容器启动后默认执行的命令及其参数,但CD能够被dockerrun后面跟的命令行参数替换。ENTRYPOINT:配置容器启动时运行的命令。2.Shell和Exec格式两种方式指定RUN、CMD和ENTRYPOINT要运行的命......
  • CAS解析
    目录什么是CAS应用场景以AtomicInteger为例,分析在Java中如何利用CAS实现原子操作的Unsafe类Unsafe类中的compareAndSwapInt缺点什么是CAS应用场景:并发我认为V的值应该是A,如果是的话,那我就把它修改成B,如果不是A(说明被别人修改过了),那我就不修改了,避免多人同时操作导致出错......
  • 4_C# 中的 ref 关键字有什么作用
    C#中的ref关键字有什么作用?参数在使用ref关键字进行引用传递时,必须在方法调用之前对其进行初始化。ref关键字既可以在进入方法之前初始化参数的值,也可以在方法内部对参数进行修改。ref参数在进入方法时保持原始值,并在方法结束后将值带回到调用处。ref关键字的作用:......
  • 1_readonly与const区别
    readonly与const区别?readonly关键字(运行时常量):字段可以在声明或构造函数中初始化,常作为运行时常量使用。const关键字(编译时常量):字段只能在该字段的声明时初始化,常作为编译时常量使用过。C#中的readonly和const都是用于声明常量的关键字,但它们之间存在一些关键的区......
  • 11_C# 中字符串 string.Empty,"",null 三者的区别
    C#中字符串string.Empty、""和null三者的区别1.string.Emptystring.Empty是一个表示空字符串的静态字段。它实际上等同于""(空字符串),但使用string.Empty可以更加清晰地表示我们需要一个空字符串。2.""(空字符串)双引号中没有任何字符的字符串被称为空字符串。它......