C#实现单例模式的6种方法小结

C#实现单例模式的6种方法小结

什么是单例模式?

单例模式是一种软件设计模式,它限制了某个类只能有一个实例,并且该实例可以从全局访问。单例模式通常用于控制资源的共享,并且可以避免竞态条件(race condition)。

单例模式的优点

  • 单例模式可以保证某个类在全局范围内只有一个对象实例,这可以减少系统中的内存占用和资源消耗
  • 单例模式可以确保某些操作只会被执行一次,这可以在程序创建和销毁对象的时候提供更加灵活的控制
  • 单例模式可以增强代码的可维护性和可扩展性,并使代码更容易实现测试驱动开发

C#实现单例模式的6种方法

方法1:使用静态变量

在C#中,可以使用静态变量来实现单例模式。静态变量只会被初始化一次,因此我们可以在类里面声明一个静态变量,并将其初始化为类的实例。每次使用该类时,我们可以直接访问这个静态变量,从而拿到唯一的实例。

public class Singleton1
{
    private static Singleton1 instance = new Singleton1();

    private Singleton1() {}

    public static Singleton1 Instance
    {
        get { return instance; }
    }
}

方法2:使用静态构造函数

在C#中,每个类都有一个静态构造函数(static constructor),它在创建类实例之前自动调用。我们可以在静态构造函数里面初始化一个静态变量,这样就可以保证类只有一个实例。

public class Singleton2
{
    private static Singleton2 instance;

    private Singleton2() {}

    static Singleton2()
    {
        instance = new Singleton2();
    }

    public static Singleton2 Instance
    {
        get { return instance; }
    }
}

方法3:使用双重检查锁定

在使用方法1和方法2实现单例模式的时候,我们需要使用锁来保证线程安全。但是由于锁的开销比较大,因此我们可以使用双重检查锁定(double-checked locking)来减少锁的使用次数,提高性能。

public class Singleton3
{
    private static Singleton3 instance;
    private static readonly object syncRoot = new object();

    private Singleton3() {}

    public static Singleton3 Instance
    {
        get
        {
            if (instance == null)
            {
                lock (syncRoot)
                {
                    if (instance == null)
                    {
                        instance = new Singleton3();
                    }
                }
            }

            return instance;
        }
    }
}

方法4:使用延迟初始化

在C#中,可以使用延迟初始化(lazy initialization)来实现单例模式。延迟初始化可以推迟对象的创建,直到第一次访问对象时才创建,从而避免资源的浪费。

public class Singleton4
{
    private static readonly Lazy<Singleton4> lazyInstance = new Lazy<Singleton4>(() => new Singleton4());

    private Singleton4() {}

    public static Singleton4 Instance
    {
        get { return lazyInstance.Value; }
    }
}

方法5:使用属性

在C#中,可以使用属性(property)来实现单例模式。属性可以在读取和写入时执行特定的代码,因此我们可以在属性的get访问器中返回唯一的类实例。

public class Singleton5
{
    private static readonly Singleton5 instance = new Singleton5();

    private Singleton5() {}

    public static Singleton5 Instance
    {
        get { return instance; }
    }
}

方法6:使用容器

在C#中,可以使用容器(container)来实现单例模式。容器可以存储对象的实例,并在需要的时候返回该实例,从而确保全局范围内只有一个对象实例。

public class Singleton6
{
    private static readonly Lazy<Singleton6> lazyInstance = new Lazy<Singleton6>(() => new Singleton6());

    private Singleton6() {}

    public static Singleton6 Instance
    {
        get { return lazyInstance.Value; }
    }
}

public class SingletonContainer
{
    private readonly Dictionary<string, object> container = new Dictionary<string, object>();

    public T GetInstance<T>() where T : class
    {
        var typeName = typeof(T).FullName;
        if (!container.ContainsKey(typeName))
        {
            container[typeName] = Activator.CreateInstance(typeof(T));
        }

        return container[typeName] as T;
    }
}

以上6种方法都可以实现单例模式,每种方法都有其优缺点。我们可以根据具体的场景选择合适的方法来实现单例模式。

示例1:使用静态变量实现单例模式

以下是一个使用静态变量实现单例模式的示例代码:

class Program
{
    static void Main(string[] args)
    {
        var instance1 = Singleton1.Instance;
        var instance2 = Singleton1.Instance;
        Console.WriteLine(instance1.GetHashCode());
        Console.WriteLine(instance2.GetHashCode());
        Console.ReadLine();
    }
}

public class Singleton1
{
    private static Singleton1 instance = new Singleton1();

    private Singleton1() {}

    public static Singleton1 Instance
    {
        get { return instance; }
    }
}

输出结果:

31133577
31133577

可以看出,两个实例的哈希码是相同的,说明它们是同一个对象。

示例2:使用容器实现单例模式

以下是一个使用容器实现单例模式的示例代码:

class Program
{
    static void Main(string[] args)
    {
        var container = new SingletonContainer();

        var instance1 = container.GetInstance<Singleton6>();
        var instance2 = container.GetInstance<Singleton6>();

        Console.WriteLine(instance1.GetHashCode());
        Console.WriteLine(instance2.GetHashCode());
        Console.ReadLine();
    }
}

public class Singleton6
{
    private static readonly Lazy<Singleton6> lazyInstance = new Lazy<Singleton6>(() => new Singleton6());

    private Singleton6() {}

    public static Singleton6 Instance
    {
        get { return lazyInstance.Value; }
    }
}

public class SingletonContainer
{
    private readonly Dictionary<string, object> container = new Dictionary<string, object>();

    public T GetInstance<T>() where T : class
    {
        var typeName = typeof(T).FullName;
        if (!container.ContainsKey(typeName))
        {
            container[typeName] = Activator.CreateInstance(typeof(T));
        }

        return container[typeName] as T;
    }
}

输出结果:

31284847
31284847

可以看出,两个实例的哈希码是相同的,说明它们是同一个对象。

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

(0)
上一篇 2023年5月15日
下一篇 2023年5月15日

相关文章

  • ASP.NET 绑定DataSet中的多个表

    ASP.NET 是一个Web应用程序框架,能够以高效的方式在Web服务器上构建动态网站、Web应用程序和Web服务。DataSet是一种轻量级对象,可用于存储多个数据表和它们之间的关系,并将其与控件进行绑定。 在ASP.NET的开发过程中,如果需要在一个页面中展示来自多个数据表的数据,可以使用DataSet,并通过绑定控件的方式来展示数据。下面是绑定Data…

    C# 2023年5月31日
    00
  • 基于C#的图表控件库 ScottPlot编译visual studio 2022

    以下是关于基于C#的图表控件库 ScottPlot编译visual studio 2022的完整攻略,过程中会包含两条示例说明: 准备工作 在开始编译ScottPlot之前,你需要准备以下环境: 安装Visual Studio 2022 IDE,可以从官方网站下载并安装。 安装.NET Core SDK,可以从官方网站下载并安装。 编译ScottPlot 打…

    C# 2023年6月7日
    00
  • 原生JS实现加载进度条

    原生JS实现加载进度条 在Web开发中,加载进度条是一个非常常见的功能。本文将介绍如何使用原生JS实现加载进度条。 步骤1:HTML结构 首先,我们需要在HTML中添加进度条的结构。可以在HTML文件中添加以下代码: <div id="progress-bar"> <div id="progress"…

    C# 2023年5月15日
    00
  • C# StringBuilder.Append()方法: 将一个字符串追加到 StringBuilder 对象的末尾

    StringBuilder是C#中用来动态生成字符串的类,可以有效地避免字符串拼接等操作因为频繁创建新的字符串对象而造成的性能问题。StringBuilder类有多种方法可以用来操作字符串,其中Append()是最常用的方法之一。 Append()方法的作用 StringBuilder.Append()方法用于在已有字符串的末尾追加新的内容。具体来说,就是将…

    C# 2023年4月19日
    00
  • .NET使用一行命令轻松生成EF Core项目框架

    dotnet ef是Entity Framework Core(EF Core)的一个命令行工具,用于管理EF Core应用程序的数据库和代码。除了提供管理数据库的命令之外,dotnet ef还可以生成和管理实体和上下文代码。本文将介绍如何使用dotnet ef动态生成代码。 一、环境准备 1、项目准备 用vs2022新建一个.NET6的asp.net co…

    C# 2023年4月27日
    00
  • C#注释的一些使用方法浅谈

    C#注释的一些使用方法浅谈 简介 注释是一种解释源代码的方法,在C#中,注释可以分为两种类型:单行注释和多行注释。 单行注释 在代码行的后面以双斜杠 // 开头,这一行的内容就被视作注释,注释可以在同一行代码的下方,说明这一行代码的作用。 示例: int a = 1; // 定义变量a,赋值为1 多行注释 多行注释又称块注释,可以用用 /* 和 */ 包围一…

    C# 2023年5月15日
    00
  • C# md5 算法实现代码

    C# MD5 算法实现,可以通过使用System.Security.Cryptography空间下的MD5类来完成。下面是完整的攻略: 步骤 1:添加命名空间 首先,在你的 C# 代码文件中,添加如下命名空间: using System.Security.Cryptography; 步骤 2:创建 MD5 对象 接下来,创建一个 MD5 对象,代码如下: M…

    C# 2023年5月31日
    00
  • C#定时任务框架Quartz.NET介绍与用法

    C#定时任务框架 Quartz.NET 介绍与用法 Quartz.NET 是一个强大的、开源的定时任务调度框架,它可以用于 C# 编程语言中。 框架介绍 Quartz.NET 与 .NET Framework 完美结合,允许开发人员在自己的应用程序中创建并组织复杂的、企业级的定时任务调度系统。它被广泛应用于金融、电信、物流等领域,可以帮助开发人员在开发定时任…

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