C#实现单例模式的多种方式

C#实现单例模式的多种方式

单例模式是设计模式中的一种,指的是创建一个类的实例后,该类只允许创建一个实例,并且提供一个访问该实例的全局访问点。在很多场景下,单例模式被广泛使用,比如线程池、缓存、配置文件等等。

在C#中实现单例模式的方式比较多,下面就介绍一些常见的实现方式,分别是:懒汉式、饿汉式、静态构造器、枚举实现、双重锁定以及 .NET 4.0+ 中新增的 Lazy 实现。

1. 懒汉式

懒汉式是指在调用获取实例的方法时才实例化对象,即只有当需要使用实例时才会去创建,因此称之为“懒汉式”。

这种方式比较简单,代码如下:

public sealed class Singleton
{
    private static Singleton instance = null;
    private Singleton() { }
    public static Singleton Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }
}

在上面的代码中,我们在访问 Instance 属性时,会先检查 instance 是否为 null,如果是,则创建一个新的 Singleton 实例,否则直接返回单例对象。

需要注意的是,这种方式并不是线程安全的,会存在多线程同时调用 Instance 属性时会创建多个实例的问题。

2. 饿汉式

相比懒汉式,饿汉式是指在程序启动时就创建好单例对象,因此称之为“饿汉式”。

这种方式比较简单,代码如下:

public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();
    private Singleton() { }
    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}

在上面的代码中,instance 被声明为 readonly,确保在多线程访问时不会被修改,因此是线程安全的。

3. 静态构造器

静态构造器是指在第一次使用类之前,.NET框架会自动调用静态构造函数来执行一些初始化操作,因此我们可以在静态构造函数中创建单例对象,示例代码如下:

public sealed class Singleton
{
    private static readonly Singleton instance = null;
    static Singleton()
    {
        instance = new Singleton();
    }
    private Singleton() { }
    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}

如上代码,静态构造器会在第一次访问 Singleton 类之前被执行,因此可以在其中执行一些初始化操作,比如创建单例对象。

需要注意的是,如果单例类的静态构造函数中抛出了异常,那么 instance 将不会被赋值,因此使用时需要特别小心。

4. 枚举实现

在 .NET 2.0 之后,C#对枚举类型进行了扩展,可以将枚举类型看做是一种特殊的单例模式实现方式。

示例代码如下:

public enum Singleton
{
    Instance
}

在上面的代码中,我们把 Singleton 定义为一个枚举类型,其只有一个成员 Instance。当我们需要访问单例对象时,只需要使用 Singleton.Instance 即可获得。

需要注意的是,枚举类型的实现方式比较巧妙,但是其存在一些限制,比如无法继承和延迟初始化等。

5. 双重锁定

双重锁定是指在判断实例是否为 null 时,使用了两个锁来确保线程安全,因此称之为“双重锁定”。

示例代码如下:

public sealed class Singleton
{
    private static readonly object syncObj = new object();
    private static Singleton instance = null;
    private Singleton() { }
    public static Singleton Instance
    {
        get
        {
            if (instance == null)
            {
                lock (syncObj)
                {
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
}

在上面的代码中,我们使用了两个锁 syncObjinstance,并使用了两次 if 语句进行判断。

需要注意的是,双重锁定的实现方式比较复杂,而且可能存在一些细微的问题,比如CPU指令重排等问题。

6. Lazy实现

在 .NET 4.0 以及更高版本中,C#新增了一个 Lazy<T> 类型,可以方便地实现延迟初始化及线程安全,示例代码如下:

public sealed class Singleton
{
    private static readonly Lazy<Singleton> lazyInstance = new Lazy<Singleton>(() => new Singleton());
    private Singleton() { }
    public static Singleton Instance
    {
        get
        {
            return lazyInstance.Value;
        }
    }
}

在上面的代码中,我们通过 Lazy<Singleton> 类型实现了单例对象的延迟初始化和线程安全,在调用 Instance 属性时才实例化对象,并且能够确保在多线程访问时只会创建一个实例。

需要注意的是,Lazy<T> 是一种非常优秀的实现方式,不仅易于使用,而且性能也比较高,需要尽量推荐使用。

总结

本文介绍了 C# 实现单例模式的多种方式,分别是懒汉式、饿汉式、静态构造器、枚举实现、双重锁定以及 .NET 4.0+ 中新增的 Lazy 实现。各种实现方式都有其优缺点,需要根据实际需求和应用场景进行选择。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#实现单例模式的多种方式 - Python技术站

(0)
上一篇 2023年6月6日
下一篇 2023年6月6日

相关文章

  • asp.net后台注册js的四种方法分享

    下面我将详细讲解asp.net后台注册js的四种方法,希望对你有所帮助。 1. 在aspx的头部使用script标签嵌入javascript代码 这种方法是比较简单的,直接在aspx页面的头部使用script标签嵌入javascript代码即可。示例如下: <head runat="server"> <script ty…

    C# 2023年5月31日
    00
  • C#下listview如何插入图片

    关于C#下listview如何插入图片,以下是详细攻略。 1. 添加图片列 首先我们需要在listview中添加一列,这一列用于存储图片。 listView1.Columns.Add("图片列", 80); 其中,”图片列”是列标题,80是列的宽度。为了方便,我们这里设置列宽为80。 2. 添加图片到列表项 接下来,我们需要添加图片到列表…

    C# 2023年6月6日
    00
  • C#实现简单记事本程序

    C#实现简单记事本程序 一、思路 记事本程序的基本功能是打开文本文件、编辑文本、保存文本等。因此,我们需要实现以下功能: 新建文本文件 打开文本文件 导入文本文件 编辑文本 保存文本 另存为 二、实现 1. 界面设计 首先,我们需要设计记事本的界面。可以采用Windows Forms应用程序进行界面设计。常见的界面元素包括MenuStrip菜单栏、ToolS…

    C# 2023年6月1日
    00
  • c#方法中调用参数的值传递方式和引用传递方式以及ref与out的区别深入解析

    请参考以下攻略: 什么是值传递和引用传递 在 C# 中,方法通过参数来接收外部传入的值,参数可以使用值传递或引用传递的方式进行传递。 值传递是传递值类型参数的方式,即方法接收的参数是原始值的副本,不影响原始值,例如基本类型 int、char、bool 等和结构体。 引用传递是传递引用类型参数的方式,即方法接收的参数是原始值的引用,会影响到原始值,例如数组、类…

    C# 2023年5月15日
    00
  • C#的字符串比较

    C#中,字符串比较有多种方式,最常用的有三种:使用“==”比较,使用Equals方法比较,使用Compare方法比较。 使用“==”比较字符串 在C#中,可以使用“==”符号来比较两个字符串是否相等,例如: string str1 = "hello"; string str2 = "world"; string str…

    C# 2023年6月1日
    00
  • .net core如何使用Redis发布订阅

    .NET Core中使用Redis发布订阅攻略 在 .NET Core 中,我们可以使用 Redis 发布订阅功能来实现消息传递和事件通知。本攻略将介绍如何在 .NET Core 中使用 Redis 发布订阅功能。 步骤 以下是使用 Redis 发布订阅功能的步骤: 安装 Redis。 在服务器上安装 Redis。可以使用官方网站提供的安装包或者使用包管理器…

    C# 2023年5月17日
    00
  • C#通过System.CommandLine快速生成支持命令行的应用程序

    接下来将为你详细讲解如何通过System.CommandLine来快速生成支持命令行的应用程序。 1. 什么是System.CommandLine System.CommandLine是用于构建命令行界面(CLI)的.NET库。它允许您快速创建参数化的命令行应用程序(如dotnet cli),同时可自动处理帮助和明确定义的参数、选项和子命令。如果您曾经使用过…

    C# 2023年6月7日
    00
  • C#通过JObject解析json对象

    下面是如何通过C#中的JObject类解析JSON对象的完整攻略: 1. 引用Newtonsoft.Json包 要使用JObject类来解析JSON对象,需要引用Newtonsoft.Json包。在Visual Studio中,可以通过NuGet包管理器安装引用。在Package Manager Console中执行以下命令即可: Install-Packa…

    C# 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部