如何借助Lazy<T>的IsValueCreated确保C#单例模式唯一性?
Lazy<T>单例中IsValueCreated的用法 我读过Jon Skeet撰写的一篇关于单例模式的文章,其中他介绍了用Lazy<T>实现单例的写法,代码如下:
public sealed class Singleton { private static readonly Lazy<Singleton> lazy = new Lazy<Singleton>(() => new Singleton()); public static Singleton Instance { get { return lazy.Value; } } private Singleton() { } }
文章末尾提到:
它还允许你通过
IsValueCreated属性检查实例是否已创建(如果有需要的话)。
IsValueCreated用于标记延迟对象是否完成初始化。我想知道,为了确保这个类始终保持单例(仅创建一个实例),应该在什么场景、怎么使用IsValueCreated属性?
核心结论
首先明确:这个基于Lazy<T>的单例实现本身已经保证了只会创建一个实例——Lazy<T>默认采用LazyThreadSafetyMode.ExecutionAndPublication线程安全模式,无论多少线程同时访问Instance属性,都只会触发一次实例化逻辑。IsValueCreated并不是用来"确保单例"的工具,它的核心作用是在不触发实例化的前提下,查询单例是否已经被初始化。
适用场景与具体用法
避免不必要的实例化:如果有业务逻辑不需要获取单例实例,但需要根据实例是否存在做分支处理,就可以用
IsValueCreated。比如:// 仅判断实例状态,不触发初始化 if (Singleton.IsInstanceCreated) { // 实例已存在时的逻辑:比如记录运行状态、清理临时关联资源 Log.Info("单例实例已完成初始化"); } else { // 实例未初始化时的逻辑:比如提前加载依赖资源、提示前置条件 PreloadRequiredResources(); }注意:不要试图用
IsValueCreated阻止实例化——只要访问Instance属性,Lazy<T>就会自动触发实例化流程。调试与监控:在排查问题或监控系统状态时,
IsValueCreated可以快速帮你确认单例的初始化状态,比如输出调试日志:Debug.WriteLine($"单例实例状态:{(Singleton.IsInstanceCreated ? "已初始化" : "未初始化")}");
单例正确性的保障要点
要确保这个类始终是单例,你只需要维持以下设计:
- 类标记为
sealed,防止被继承后通过子类创建新实例 - 构造函数设为
private,禁止外部直接实例化 - 不要通过反射等手段破坏
Lazy<T>或单例类的封装
IsValueCreated只是一个状态查询工具,和单例的正确性没有直接关联——单例的唯一性是由Lazy<T>的线程安全机制原生保证的。
内容的提问来源于Stack Exchange,提问作者OpenStack

