Lazy(延迟初始化)用法
1. 简介
从net 4.0开始,C#开始支持延迟初始化,通过Lazy关键字,我们可以声明某个对象为仅仅当第一次使用的时候,再初始化,如果一直没有调用,那就不初始化,省去了一部分不必要的开销,提升了效率,同时Lazy是天生线程安全的
2. 应用场景
对象创建成本高且程序可能不会使用它。
例如,假定内存中有具有 Orders 属性的 Customer 对象,该对象包含大量 Order 对象,初始化这些对象需要数据库连接。 如果用户永远不要求显示 Orders 或在计算中使用该数据,则无需使用系统内存或计算周期来创建它。 通过使用 Lazy 来声明 Orders 对象用于迟缓初始化,可以避免在不使用该对象时浪费系统资源。
对象创建成本高,且希望将其创建推迟到其他高成本操作完成后。
例如,假定程序在启动时加载多个对象实例,但是只需立即加载其中一部分。 可以通过推迟初始化不需要的对象,直到创建所需对象,提升程序的启动性能。
3. Lazy基本用法
3.1. 方式一:构造时使用默认的初始化方式
在使用Lazy时,如果没有在构造函数中传入委托,则在首次访问值属性时,将会使用Activator.CreateInstance来创建类型的对象,如果此类型没有无参数的构造函数时将会引发运行时异常。
1 using System; 2 3 namespace LazyUsage 4 { 5 class LazyDemo 6 { 7 static void Main() 8 { 9 Lazy<Data> lazyData = new Lazy<Data>(); 10 Console.WriteLine("Main->is lazyData Initialized? value = " + lazyData.IsValueCreated); 11 lazyData.Value.Print();//此处访问时才会将Data真正的初始化 12 Console.WriteLine("Main->is lazyData Initialized? value = " + lazyData.IsValueCreated); 13 14 Console.ReadKey(); 15 } 16 } 17 18 class Data 19 { 20 public Data() 21 { 22 Console.WriteLine("Data::.ctor->Initialized"); 23 } 24 25 public void Print() 26 { 27 Console.WriteLine("Data::Print->println"); 28 } 29 } 30 }
执行结果:
Main->is lazyData Initialized? value = False
Data::.ctor->Initialized
Data::Print->println
Main->is lazyData Initialized? value = True
3.2. 方式二:构造时使用指定的委托初始化
using System; namespace LazyUsage { class LazyDemo { static void Main() { //指定委托来初始化Data Lazy<Data> lazyData = new Lazy<Data>( () => { Console.WriteLine("Main->lazyData will be Initialized!"); return new Data("Test"); }); Console.WriteLine("Main->is lazyData Initialized? value = " + lazyData.IsValueCreated); lazyData.Value.Print(); Console.WriteLine("Main->is lazyData Initialized? value = " + lazyData.IsValueCreated); Console.ReadKey(); } } class Data { public string Name { get; private set; } public Data(string name) { Name = name; Console.WriteLine("Data::.ctor->Initialized,name = "+name); } public void Print() { Console.WriteLine("Data::Print->name = " + Name); } } }
执行结果:
Main->is lazyData Initialized? value = False
Main->lazyData will be Initialized!
Data::.ctor->Initialized,name = Test
Data::Print->name = Test
Main->is lazyData Initialized? value = True
4. Lazy.Value的使用
Lazy对象创建后,并不会立即创建对应的对象,只有在变量的Value属性被首次访问时才会真正的创建,同时会将其缓存到Value中,以便将来访问。
Value属性是只读的,也就意味着如果Value存储了引用类型,将无法为其分配新对象,只可以更改此对象公共的属性或者字段等,如果Value存储的是值类型,那么就不能修改其值了,只能通过再次调用变量的函数使用新的参数来创建新的变量
在Lazy对象创建后,在首次访问变量的Value属性前,
5. 扩展
5.1 实现延迟属性
class Customer { private Lazy<Orders> _orders; public string CustomerID {get; private set;} public Customer(string id) { CustomerID = id; _orders = new Lazy<Orders>(() => { return new Orders(this.CustomerID); }); } public Orders MyOrders { get { return _orders.Value; } } }
在Lazy.Value的使用中可以得知:Value的属性是只读的,所以示例中只提供了Get的访问器,并未提供Set的访问器。
如果需要支持读取与写入属性的话,则Set访问器必须创建一个新的Lazy对象,同时必须编写自己的线程安全代码才能执行此操作
鸣谢:
https://blog.csdn.net/mingtianqingtian/article/details/112174792
https://docs.microsoft.com/zh-cn/dotnet/framework/performance/lazy-initialization
本文来自博客园,作者:{春光牛牛,yak},转载请注明原文链接:https://www.cnblogs.com/yakniu/p/16342507.html
欢迎各位大佬们评论指正
QQ讨论群:610129902
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南