【.NET Core】Lazy<T> 实现延迟加载详解
【.NET Core】Lazy 实现延迟加载详解
文章目录
- 【.NET Core】Lazy<T> 实现延迟加载详解
- 一、概述
- 二、Lazy<T>是什么
- 三、Lazy基本用法
- 3.1 构造时使用默认的初始化方式
- 3.2 构造时使用指定的委托初始化
- 四、Lazy.Value使用
- 五、Lazy扩展用法
- 5.1 实现延迟属性
- 5.2 `Lazy`实现惰性加载单例模式
- 六、Lazy常用扩展方法

一、概述
延迟初始化是一种将对象的创建延迟到第一次需要用时的技术。简而言之,就是对象的初始化发生在第一次需要调用的时候执行。通常所说的延迟初始化和延迟实例化的意思是相同。通过使用延迟基础,可以避免应用程序不必要的计算和内存消耗。
从.NET 4.0开始,可以使用Lazy来实现对象的延迟初始化,从而优化系统的性能。延迟初始化就是将对象的初始化延迟到第一次使用该对象时。延迟初始化是我们优化程序性能的一种方式。如创建一个对象时需要花费很大的开销,而这一对象在系统运行过程中不一定会用到,这时就可以使用延迟初始化,在第一次使用该对象时再对其进行实例化。如果没有用在整个应用程序生命期则不需要初始化,使用延迟初始化可以提高程序的利用率,从而使程序占用更少的内存。
二、Lazy是什么
Lazy是一个类,用于实现惰性加载(Lazy Initialization)
。惰性加载是指对象的创建被推迟,直到第一次被使用时,Lazy<T>
允许在第一次访问对象时进行初始化,这对于大型或资源密集型对象的性能优化非常有用。可以通过提供一个委托Delegate
来延迟初始化对象。Lazy<T>
确保所有线程使用同一个惰性加载对象的实例,并且丢弃使用的实例,从而优化内存使用。
- 延迟初始化(Lazy Initialization):
Lazy<T>
允许你将对象的创建推迟到首次访问时。 - 线程安全(Thread-Safe):
Lazy<T>
提供了线程安全的延迟初始化,确保在多线程环境中也能正确工作。 - 自动丢弃未使用的实例:如果对象未被使用,
Lazy<T>
会自动丢弃初始化失败的实例,优化内存使用。 - 支持复杂的初始化逻辑:你可以提供一个委托,允许你在初始化对象时执行复杂的逻辑。
- Value 属性:通过
Lazy<T>.Value
属性访问延迟初始化的对象。
三、Lazy基本用法
3.1 构造时使用默认的初始化方式
在使用Lazy时,如果没有在构造函数中传入委托,则在首次访问值属性时,将会使用Activator.CreateInstance
来创建类型的对象,如果此类型没有无参数的构造函数时将会引发运行时异常。
本文实例类:
public class Employee{public int Id { get; set; } = 101;public string? Code { get; set; } = "G001";public string? Name { get; set; } = "爷叔";public string? Address { get; set; } = "上海市黄河路1001号";public Employee() {}public Employee(int id,string code,string name,string address) {this.Id = id;this.Code = code;this.Name = name;this.Address = address;}public void Show() {Console.WriteLine($"Id={Id},Code={Code},Name={Name},Address={Address}");}
}
public static void Main(string[] arg)
{Lazy<Employee> lazyEmployee = new Lazy<Employee>();Console.WriteLine($"Main->is lazyData Initialized? value = {lazyEmployee.IsValueCreated}");lazyEmployee.Value.Show();//此处访问时才会将Data真正的初始化Console.WriteLine($"Main->is lazyData Initialized? value = {lazyEmployee.IsValueCreated}");
}
运行结果
Main->is lazyData Initialized? value = False
Id=101,Code=G001,Name=爷叔,Address=上海市黄河路1001号
Main->is lazyData Initialized? value = True
3.2 构造时使用指定的委托初始化
public static void Main(string[] arg){Lazy<Employee> lazyEmployee = new Lazy<Employee>(() =>{Console.WriteLine("Main->lazyData will be Initialized!");return new Employee(2,"G003","阿宝","上海市南京路001号");});Console.WriteLine($"Main->is lazyData Initialized? value = {lazyEmployee.IsValueCreated}");lazyEmployee.Value.Show();//此处访问时才会将Data真正的初始化Console.WriteLine($"Main->is lazyData Initialized? value = {lazyEmployee.IsValueCreated}");}
运行结果
Main->is lazyData Initialized? value = False
Main->lazyData will be Initialized!
Id=2,Code=G003,Name=阿宝,Address=上海市南京路001号
Main->is lazyData Initialized? value = True
四、Lazy.Value使用
由上面两个应用,可以看出Lazy
对象创建后,并不会立即创建对应地对象,只有在变量的Value
属性被首次访问时才会真正地创建,同时会将其缓存到Value
中,以便将来访问。
Value
属性是只读的,也就意味着如果Value
存储了引用类型,将无法为其分配新对象,只可以更改此对象公共地属性或字段等,如果Value
存储的是值类型。那么就不能修改其值,只能通过再次调用变量的函数使用新的参数来创建的变量。
在Lazy
对象创建后,在首次访问变量的Value
属性前。
五、Lazy扩展用法
5.1 实现延迟属性
public class Customer
{private Lazy<Employee> employee;public int CustomerId { get; private set; }public Customer(int id, string code, string name, string address){this.CustomerId = id;employee = new Lazy<Employee>(() => new Employee(this.CustomerId, "C001", "李阿宝", "上海市南京西路1100号"));}
}
从上面介绍Lazy.Value
中可以得知:Value的属性是只读,示例中只提供了Get的访问器,并未提供Set的访问器。如果需要支持读取与写入属性的话,则Set访问器必须创建一个新地Lazy
对象,同时必须编写自己的线程安全代码才能执行此操作。
5.2 Lazy
实现惰性加载单例模式
public class Singleton<T> where T : class{private static readonly Lazy<T> current = new Lazy<T>(() => Activator.CreateInstance<T>(), // factory methodtrue); // double lockspublic static object Current{get { return current.Value; }}}
六、Lazy常用扩展方法
-
public Lazy (bool isThreadSafe):
isThreadSafe 的布尔参数,该方法参数用于指定是否从多线程访问 Value 属性。 如果想要仅从一个线程访问属性,则传入 false 以获取适度的性能优势。 如果想要从多线程访问属性,则传入 true 以指示 Lazy 实例正确处理争用条件(初始化时一个线程引发异常)。
-
public Lazy (LazyThreadSafetyMode mode)
提供线程安全模式
-
public Lazy (Func valueFactory)
lambda 表达式传递给新的 Lazy 对象的构造函数。 下一次访问 Value 属性将导致新 Lazy 的初始化,并且其 Value 属性此后会返回已分配给该属性的新值。
相关文章:

【.NET Core】Lazy<T> 实现延迟加载详解
【.NET Core】Lazy 实现延迟加载详解 文章目录 【.NET Core】Lazy<T> 实现延迟加载详解一、概述二、Lazy<T>是什么三、Lazy基本用法3.1 构造时使用默认的初始化方式3.2 构造时使用指定的委托初始化 四、Lazy.Value使用五、Lazy扩展用法5.1 实现延迟属性5.2 Lazy实现…...

坑记(HttpInputMessage)
一、背景知识 public interface HttpInputMessage extends HttpMessage Represents an HTTP input message, consisting of headers and a readable body.Typically implemented by an HTTP request on the server-side, or a response on the client-side.Since: 3.0 Author:…...

day04打卡
day04打卡 面试题 02.07. 链表相交 时间复杂度:O(N),空间复杂度:O(1) 第一想法:求出两个链表长度,走差距步,再遍历找有没有相交 /*** Definition for singly-linked list.* struct ListNode {* int…...

语义分割miou指标计算详解
文章目录 1. 语义分割的评价指标2. 混淆矩阵计算2.1 np.bincount的使用2.2 混淆矩阵计算 3. 语义分割指标计算3.1 IOU计算方式1(推荐)方式2 3.2 Precision 计算3.3 总体的Accuracy计算3.4 Recall 计算3.5 MIOU计算 参考 MIoU全称为Mean Intersection over Union,平均…...

Unity3d 实现直播功能(无需sdk接入)
Unity3d 实现直播功能 需要插件 :VideoCapture 插件地址(免费的就行) 原理:客户端通过 VideoCapture 插件实现推流nodejs视频流转服务进行转发,播放器实现rtmp拉流 废话不多说,直接上 CaptureSource我选择的是屏幕录制,也可以是其他源 CaptureType选择LIVE–直播形式 LiveSt…...

计算机缺失msvcr100.dll如何修复?分享五种实测靠谱的方法
在计算机系统的日常运行与维护过程中,我们可能会遇到一种特定的故障场景,即系统中关键性动态链接库文件msvcr100.dll的丢失。msvcr100.dll是Microsoft Visual C Redistributable Package的一部分,对于许多基于Windows的应用程序来说ÿ…...

面试宝典进阶之redis缓存面试题
R1、【初级】Redis常用的数据类型有哪些? (1)String(字符串) (2)Hash(哈希) (3)List(列表) (4)Se…...

调试(c语言)
前言: 我们在写程序的时候可能多多少少都会出现一些bug,使我们的程序不能正常运行,所以为了更快更好的找到并修复bug,使这些问题迎刃而解,学习好如何调试代码是每个学习编程的人所必备的技能。 1. 什么是bug…...

opencv-4.8.0编译及使用
1 编译 opencv的编译总体来说比较简单,但必须记住一点:opencv的版本必须和opencv_contrib的版本保持一致。例如opencv使用4.8.0,opencv_contrib也必须使用4.8.0。 进入opencv和opencv_contrib的github页面后,默认看到的是git分支&…...

Jmeter 性能-监控服务器
Jmeter监控Linux需要三个文件 JMeterPlugins-Extras.jar (包:JMeterPlugins-Extras-1.4.0.zip) JMeterPlugins-Standard.jar (包:JMeterPlugins-Standard-1.4.0.zip) ServerAgent-2.2.3.zip 1、Jemter 安装插件 在插件管理中心的搜索Servers Perform…...

Excel学习
文章目录 学习链接Excel1. Excel的两种形式2. 常见excel操作工具3.POI1. POI的概述2. POI的应用场景3. 使用1.使用POI创建excel2.创建单元格写入内容3.单元格样式处理4.插入图片5.读取excel并解析图解POI 4. 基于模板输出POI报表5. 自定义POI导出工具类ExcelAttributeExcelExpo…...

【技能---labelme软件的安装及其使用--ubuntu】
文章目录 概要Labelme 是什么?Labelme 能干啥? Ubuntu20.04安装Labelme1.Anaconda的安装2.Labelme的安装3.Labelme的使用 概要 图像检测需要自己的数据集,为此需要对一些数据进行数据标注,这里提供了一种图像的常用标注工具——la…...

回归预测 | Matlab实现SSA-CNN-LSTM-Attention麻雀优化卷积长短期记忆神经网络注意力机制多变量回归预测(SE注意力机制)
回归预测 | Matlab实现SSA-CNN-LSTM-Attention麻雀优化卷积长短期记忆神经网络注意力机制多变量回归预测(SE注意力机制) 目录 回归预测 | Matlab实现SSA-CNN-LSTM-Attention麻雀优化卷积长短期记忆神经网络注意力机制多变量回归预测(SE注意力…...

css垂直水平居中的几种实现方式
垂直水平居中的几种实现方式 一、固定宽高: 1、定位 margin-top margin-left .box-container{position: relative;width: 300px;height: 300px;}.box-container .box {width: 200px; height: 100px;position: absolute; left: 50%; top: 50%;margin-top: -50px;…...

OpenHarmony之hdc
OpenHarmony之hdc 简介 hdc(OpenHarmony Device Connector)是 OpenHarmony 为开发人员提供的用于调试的命令行工具,通过该工具可以在Windows/Linux/MacOS等系统上与开发机或者模拟器进行交互。 类似于Android的adb,和adb类似&a…...

【爬虫实战】-爬取微博之夜盛典评论,爬取了1.7w条数据
前言: TaoTao之前在前几期推文中发布了一个篇weibo评论的爬虫。主要就是采集评论区的数据,包括评论、评论者ip、评论id、评论者等一些信息。然后有很多的小伙伴对这个代码很感兴趣。TaoTao也都给代码开源了。由于比较匆忙,所以没来得及去讲这…...

CST2024的License服务成功启动,仍报错——“The desired daemon is down...”,适用于任何版本!基础设置遗漏!
CST2024的License服务成功启动,仍报错——“The desired daemon is down…”,适用于任何版本!基础设置遗漏! CST2024的License服务成功启动后报错 若不能成功启动License服务,有可能是你的计算机名称带中文ÿ…...

matlab中any()函数用法
一、帮助文档中的介绍 B any(A) 沿着大小不等于 1 的数组 A 的第一维测试所有元素为非零数字还是逻辑值 1 (true)。实际上,any 是逻辑 OR 运算符的原生扩展。 二、解读 分两步走: ①确定维度;②确定运算规则 以下面二维数组为例 >>…...

Apache ECharts | 一个数据可视化图表库
文章目录 1、简介1.1、主要特点1.2、使用场景 2、安装方式一:从下载的源代码或编译产物安装方法二:从 npm 安装方法三:⭐定制安装echarts.js 3、使用 官网: 英语:https://echarts.apache.org/en/index.html 中文&a…...

m1 + swoole(hyperf) + yasd + phpstorm 安装和debug
参考文档 Mac M1安装报错 checking for boost... configure: error: lib boost not found. Try: install boost library Issue #89 swoole/yasd GitHub 1.安装boost库 brew install boostbrew link boost 2.下载yasd git clone https://github.com/swoole/yasd.git 3.编…...

group by 查询慢的话,如何优化?
1、说明 根据一定的规则,进行分组。 group by可能会慢在哪里?因为它既用到临时表,又默认用到排序。有时候还可能用到磁盘临时表。 如果执行过程中,会发现内存临时表大小到达了上限(控制这个上限的参数就是tmp_table…...

【重学C语言】一、C语言简介
【重学C语言】一、C语言简介 什么是编程语言?编程语言 C语言发展史C语言标准变迁开发软件CLion安装步骤 VIsual Studio安装步骤 Clion 和 VS2022 绑定 电脑常识 什么是编程语言? 人类语言:语言就是人类进行沟通交流的表达方式,应…...

【MATLAB源码-第109期】基于matlab的哈里斯鹰优化算发(HHO)机器人栅格路径规划,输出做短路径图和适应度曲线。
操作环境: MATLAB 2022a 1、算法描述 哈里斯鹰优化算法(Harris Hawk Optimization, HHO)是一种受自然界捕食行为启发的优化算法。它基于哈里斯鹰的捕猎策略和行为模式,主要用于解决各种复杂的优化问题。这个算法的核心特征在于…...

NestJS 如何自定义中间件以及实际项目基于中间件提升项目开发效率
前言 NestJS 作为一个强大的 Node.js 框架,允许你通过中间件对请求和响应进行处理。中间件的概念在其他许多框架中也存在,它们在请求处理流程的早期执行,因此非常适合执行如日志记录、请求验证、设置响应头等任务。 在这篇教程中࿰…...

CMake入门教程【核心篇】设置和使用缓存变量
😈「CSDN主页」:传送门 😈「Bilibil首页」:传送门 😈「动动你的小手」:点赞👍收藏⭐️评论📝 文章目录 概述设置缓存变量使用缓存变量更改缓存变量完整代码示例实战使用技巧注意事项总结与分析...

MinIO (五) .net core实现分片上传
开发环境 Win11 vs2022 appsettings.json添加配置项 //minIO配置"MinIO": {//服务器IP"Endpoint": "192.168.xx.xx:9090",//账号"AccessKey": "3xR7i4zs1vLnxxxxxxxx",//密码"SecretKey": "P6bAnyzJm47Ub…...

如何有效提高矢量网络分析仪的动态范围
动态范围是网络分析仪(VNA)接收机的最大输入功率与最小可测量功率(本底噪声)之间的差值,如图所示,要使测量有效,输入信号必须在这些边界内。 如果需要测量信号幅度非常大的变化,例如…...

Python 安卓开发:Kivy、BeeWare、Flet、Flutter
kivy:https://github.com/kivy python-for-android :https://python-for-android.readthedocs.io/en/latest/ BeeWare:https://docs.beeware.org/en/latest/ Flet:https://github.com/flet-dev/flet 把 PySide6 移植到安卓上去&a…...

50天精通Golang(第16天)
beego框架介绍和流程分析 beego官方文档:https://beego.me/ 一、beego框架介绍 1.1 beego框架介绍–beego简介 1.1.1 什么是beego beego是一个使用Go语言来开发WEB引用的GoWeb框架,该框架起始于2012年,由一位中国的程序员编写并进行公开…...

imx6ull基于yocto工程的l汇编点亮ed
通过汇编点亮led 在裸机状态下通过汇编点亮led,即没有操作系统,(uboot kernel rootfs 都不需要实现)。 led点亮原理 1.GPIO复用 根据原理图,找到led对应的引脚(pin),复用为GPIO(只有GPIO才能…...