C#设计模式 单例模式实现方式

在 C# 中实现单例模式有多种方式,以下为 6 种常见的 C# 单例实现方式,并说明它们的优缺点和适用场景。


1. 饿汉式(Eager Initialization)

类加载时就创建实例,线程安全。

csharp 复制代码
public sealed class EagerSingleton
{
    private static readonly EagerSingleton instance = new EagerSingleton();

    // 显式静态构造函数(可选),确保在首次访问前初始化
    static EagerSingleton() { }

    private EagerSingleton() { }

    public static EagerSingleton Instance => instance;
}

✅ 优点:线程安全、简单

❌ 缺点:不能懒加载,可能浪费资源


2. 懒汉式(Lazy, 非线程安全)

首次调用时创建实例,但多线程下不安全(仅用于教学,不推荐生产使用)。

csharp 复制代码
public sealed class LazyUnsafeSingleton
{
    private static LazyUnsafeSingleton instance;

    private LazyUnsafeSingleton() { }

    public static LazyUnsafeSingleton Instance
    {
        get
        {
            if (instance == null)
                instance = new LazyUnsafeSingleton();
            return instance;
        }
    }
}

❌ 不适用于多线程环境


3. 加锁懒汉式(线程安全但性能差)

每次访问都加锁,保证线程安全但效率低。

csharp 复制代码
public sealed class LockedSingleton
{
    private static LockedSingleton instance;
    private static readonly object lockObj = new object();

    private LockedSingleton() { }

    public static LockedSingleton Instance
    {
        get
        {
            lock (lockObj)
            {
                if (instance == null)
                    instance = new LockedSingleton();
                return instance;
            }
        }
    }
}

✅ 线程安全

❌ 每次都加锁,性能开销大


4. 双重检查锁定(Double-Checked Locking)

兼顾懒加载和性能,线程安全。

csharp 复制代码
public sealed class DoubleCheckedSingleton
{
    private static volatile DoubleCheckedSingleton instance;
    private static readonly object lockObj = new object();

    private DoubleCheckedSingleton() { }

    public static DoubleCheckedSingleton Instance
    {
        get
        {
            if (instance == null)
            {
                lock (lockObj)
                {
                    if (instance == null)
                        instance = new DoubleCheckedSingleton();
                }
            }
            return instance;
        }
    }
}

✅ 线程安全、懒加载、性能较好

⚠️ 需要 volatile 防止指令重排序(C# 中 volatile 确保内存可见性)


5. 静态内部类(C# 中用嵌套类模拟)

C# 没有 Java 那样的"静态内部类自动懒加载"语义,但可以通过 嵌套私有类 + 静态字段 实现类似效果:

csharp 复制代码
public sealed class NestedSingleton
{
    private NestedSingleton() { }

    public static NestedSingleton Instance => NestedHolder.instance;

    private static class NestedHolder
    {
        internal static readonly NestedSingleton instance = new NestedSingleton();
    }
}

✅ 利用 C# 类型初始化器(Type Initializer)的懒加载和线程安全特性

✅ 推荐使用(简洁、高效、安全)

💡 C# 规范保证:静态字段的初始化在类型首次被使用时由 CLR 自动完成,且是线程安全的。


6. 使用 Lazy<T>(.NET 推荐方式)

.NET 提供了 Lazy<T> 类,天然支持线程安全的懒加载。

csharp 复制代码
public sealed class LazyNetSingleton
{
    private static readonly Lazy<LazyNetSingleton> lazy =
        new Lazy<LazyNetSingleton>(() => new LazyNetSingleton());

    private LazyNetSingleton() { }

    public static LazyNetSingleton Instance => lazy.Value;
}

✅ 最简洁、最安全、最符合 .NET 习惯

✅ 可通过 LazyThreadSafetyMode 控制线程安全级别(默认是完全线程安全)

默认使用 LazyThreadSafetyMode.ExecutionAndPublication,即线程安全。


总结:C# 单例实现推荐排序

方式 懒加载 线程安全 简洁性 推荐度
Lazy<T> ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
嵌套类(Nested Holder) ⭐⭐⭐ ⭐⭐⭐⭐
双重检查锁定 ⭐⭐ ⭐⭐⭐
饿汉式 ⭐⭐⭐ ⭐⭐
加锁懒汉式
非线程安全懒汉式 ⭐⭐

✅ 最佳实践(推荐写法)

csharp 复制代码
public sealed class Singleton
{
    private static readonly Lazy<Singleton> lazy = 
        new Lazy<Singleton>(() => new Singleton());

    private Singleton() { }

    public static Singleton Instance => lazy.Value;
}

这个版本:

  • 线程安全
  • 懒加载
  • 代码简洁
  • 符合 .NET 最佳实践
相关推荐
玩泥巴的2 小时前
飞书 .NET SDK 事件处理的幂等性与去重机制
c#·.net·二次开发·飞书
在路上看风景2 小时前
3.2 FileStream
c#
zwm2698888152 小时前
6号楼 部分声光24v电压达不到,显示11v
c#
xiaolyuh1233 小时前
Spring 框架 核心架构设计 深度详解
spring·设计模式·spring 设计模式
椒颜皮皮虾7 小时前
TensorRtSharp:在 C# 世界中释放 GPU 推理的极致性能
c#·tensorrt
行止957 小时前
WinForms 彻底隐藏 滚动条的终极解决方案
c#
bugcome_com7 小时前
WPF样式进阶实战:外置样式+MVVM主题切换+样式优先级全解析
c#·.net·wpf
时光追逐者8 小时前
TIOBE 公布 C# 是 2025 年度编程语言
开发语言·c#·.net·.net core·tiobe
观无8 小时前
固高运动控制卡(GST800)基础应用分享
c#
flysh059 小时前
如何利用 C# 内置的 Action 和 Func 委托
开发语言·c#