Lazy通过延迟对象创建至首次使用,解决高开销对象提前初始化导致的性能浪费问题。它在访问Value时才执行初始化,并支持线程安全模式配置,适用于单例、配置加载等场景,提升启动速度与资源利用率。
c#中的应用与性能优势">
在C#中,Lazy
延迟初始化解决了什么问题?
某些对象创建开销大,比如读取大量数据、建立数据库连接或加载复杂配置。如果程序启动时就实例化这些对象,即使后续并不一定用到,也会拖慢启动速度并浪费内存。
Lazy
如何使用 Lazy
基本用法非常简单:
// 定义一个延迟初始化的字符串集合 private static readonly Lazy> _expensiveList = new Lazy
>(() => { // 模拟耗时操作 Thread.Sleep(1000); return new List
{ "A", "B", "C" }; }); // 使用时才初始化 List data = _expensiveList.Value; // 第一次调用时才执行初始化
上面的例子中,() => { ... } 是一个委托,定义了如何创建目标对象。这个委托只会在首次访问 .Value 时执行一次,之后重复访问会返回缓存的结果。
线程安全与性能优势
Lazy
- 默认模式(ExecutionAndPublication):确保多线程下只初始化一次,适合大多数场景。
- PublicationOnly:允许多个线程同时初始化,但只保留第一个完成的结果。
- None:不保证线程安全,性能最高,适用于单线程环境。
你可以通过构造函数指定模式:
new Lazy>(initializer, LazyThreadSafetyMode.ExecutionAndPublication);
由于避免了不必要的提前计算和对象分配,Lazy
- 单例模式中的延迟加载
- 配置或服务容器的惰性解析
- 大型集合或资源密集型对象的按需构建
- 递归结构中避免过早求值
常见应用场景举例
比如在一个服务类中,某个日志处理器开销大且可能不用:
public class DataService
{
private readonly Lazy _logger = new Lazy(() => new Logger("log.txt"));
public void DoWork()
{
// 只有出错时才真正创建日志器
if (errorOccured)
_logger.Value.LogError("Something went wrong");
}
}
这样,大多数正常流程不会承担日志器的初始化开销。
基本上就这些。Lazy











