延迟初始化解决“要不要初始化”的时机问题,适用于创建耗资源且可能不被访问的对象;正确写法为readonly字段,线程安全需权衡,异步场景应封装Task。
延迟初始化不是让对象“造得更快”,而是让它“不急着造”。它解决的是“要不要初始化”的时机问题,而不是“怎么初始化更快”的性能问题。只有当对象构造开销大、且使用概率不高时,才值得用 lazy
什么时候该用延迟初始化
核心判断标准就两条:
- 对象创建过程耗资源:比如要连数据库、读大文件、解析复杂配置、加载大量 UI 控件
- 该对象在程序生命周期中可能根本不会被访问:例如某个高级功能模块用户极少打开,或某类错误处理逻辑只在异常路径触发
典型场景包括:ASP.NET Core Controller 中按需加载重型配置服务、WinForms 启动时不立即构建隐藏 Tab 页的控件树、单元测试中模拟慢速外部依赖。
Lazy 的正确写法
常见错误是把 Lazy
public Lazy> Items => new Lazy
>(LoadItems);
正确做法是声明为 readonly 字段,确保整个生命周期只创建一次 Lazy 实例:
✔ 正确示范:private readonly Lazy> _items = new Lazy
>(LoadItems);
public List
注意:字段必须是 readonly,否则可能被意外重赋值,导致重复初始化。
线程安全与性能取舍
默认的 Lazy
-
new Lazy
(factory, isThreadSafe: false) —— 避免无谓锁竞争 - 若需更高性能且能接受“首次写入即发布”,可用 LazyThreadSafetyMode.PublishOnFirstWrite
- 多线程高频读取 + 初始化只一次 → 保留默认即可
异步场景不能直接用 Lazy
Lazy
正确解法是把 Task 封装进去:
private readonly Lazy
public async Task> GetDataAsync() => await _data.Value;
这样 _data.Value 每次返回的是同一个 Task 实例,既避免重复请求,又保持异步语义清晰。

















