【.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 属性此后会返回已分配给该属性的新值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/619489.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

翱翔与深耕:鸟型与青蛙型数学家在学科发展中的互补共生与卓越贡献

在弗里曼•戴森的知名演讲《鸟和青蛙》中&#xff0c;他以富有诗意的比喻揭示了数学家们的两种迥异特质与角色定位。戴森将那些具有前瞻视野、能够跨越学科界限&#xff0c;力图构建统一理论框架的数学家形象地比作“鸟”&#xff0c;而将专注于解决具体问题&#xff0c;深入挖…

MySQL 日志之二进制日志-binlog

1、简介 MySQL 的二进制日志记录了对 MySQL 所有的更改操作&#xff0c;不包括 select 和 show 等操作。二进制日志文件主要有&#xff1a;数据恢复、主从复制、审计&#xff08;判断是否有注入攻击&#xff09;等作用。 2、二进制日志参数配置 2.1、文件参数配置 linux 中 My…

安装nvidia driver出现 the cc vision check falied

这里提示说的需要gcc12,但是我只有gcc11,所以就报错了&#xff0c;说一说我自己的解决方法&#xff1a; 安装gcc12和g12,再切换版本为gcc12 安装gcc12: sudo apt install gcc-12安装g12: sudo apt -y install g-12切换版本&#xff1a;参考博客

惯性导航---里程计非完整性约束

惯性导航—里程计非完整性约束 1 非完整性约束原理 在进行管道中心线定位时&#xff0c;惯性导航系统在初始化后通过不断地力学编排更新载体的姿态、速度和位置信息&#xff0c;但是由于传感器是惯性器件&#xff0c;其导航误差会不断累积&#xff0c;这便需要借助外界观测量辅…

Python 分支结构之if语句

在之前编写的Python中我们都是一条一条的编写的语句&#xff0c;没有任何条件或判断&#xff0c;程序会按照代码编写顺序依次执行&#xff0c;这种编写结构叫顺序结构&#xff0c;是编程中最基本的控制结构。除了顺序机构&#xff0c;还有一个比较基本的控制结构&#xff0c;那…

Linux的SSH服务

一.SSH服务简介 1.什么是SSH SSH&#xff08;Secure Shell&#xff09;是一种安全通道协议&#xff0c;主要用来实现字符界面的远程登录、远程复制等功能。SSH 协议对通信双方的数据传输进行了加密处理&#xff0c;其中包括用户登录时输入的用户口令&#xff0c;SSH 为建立在应…

【Linux技术专题】「夯实基本功系列」带你一同学习和实践操作Linux服务器必学的Shell指令(文件处理指令-上)

文件处理指令-上 背景前言专栏介绍面向对象重点内容文件处理命令file格式[options] 主要参数简单说明使用案例 mkdir格式[options] 主要参数应用实例 grep格式主要参数[optionsl 主要参数 应用实例pattern正则表达式主要参数 应用实例fgrep和egrep dd格式[options]主要参数 应用…

linux 网络设置

查看linux基础的网络配置 命令 网关route -nip 地址ifconfig / ip aDNS 服务器cat /etc/resolv.conf主机名hostname路由route -n网络连接状态ss / netstat 一&#xff0c;ifconfig 查看网络接口信息 &#xff08;一&#xff09;ifconfig …

设计模式—— 单例设计模式

单例设计模式 什么是单例模式 单例模式是一种对象创建型模式&#xff0c;使用单例模式&#xff0c;可以保证为一个类只生成唯一的实例对象。也就是说&#xff0c;在整个程序空间中&#xff0c;该类只存在一个实例对象。 为什么使用单例模式 在应用系统开发中&#xff0c;我…

聊聊PowerJob的UseCacheLock

序 本文主要研究一下PowerJob的UseCacheLock UseCacheLock tech/powerjob/server/core/lock/UseCacheLock.java Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface UseCacheLock {String type();String key();int concurrencyLevel(); }Use…

【MIdjourney】镜头效果关键词

1.景深(depth of field) 景深&#xff08;DOF&#xff09;&#xff0c;是指在摄影机镜头或其他成像器前沿能够取得清晰图像的成像所测定的被摄物体前后距离范围。镜头光圈、镜头距离、及焦平面到拍摄物的距离是影响景深的重要因素。 在MIdjourney中&#xff0c;该关键字会使得…

数字化时代,CDMP/CDGA认证企业个人都需要

&#x1f3af;数字化时代&#xff0c;CDMP(数据管理专业人士)和CDGA(数据治理工程师)认证对于企业和个人来说都是非常重要的。 &#x1f4d2;对于企业而言&#xff1a; ✅为企业赋能 数字化培训是企业在数字化转型中的重要考核标准之一。国资委、工信部、银保监会等都有明确的要…

【STM32读取HX711的函数】

[两个普通IO读取HX711数据的函数-主芯片是STM32F407] 以下是.h文件中的内容&#xff1a; #ifndef __hx711_h #define __hx711_h #define HX711CH1_DIO_GROUP GPIOA #define HX711CH1_CLK_GROUP GPIOA #define HX711CH1_DIO_PIN GPIO_Pin_1 #define HX711CH1_CLK_PIN GPIO_Pin…

深入浅出 Golang 中的参数传递机制

目录 什么是值传递 (Pass by Value) 引用传递 (Pass by Reference) Golang 中的参数传递方式 基本类型的值传递 切片的“引用”传递 使用指针实现引用传递 结构体的值传递 结构体指针的传递 小结 值传递&#xff08;Pass by Value&#xff09;和引用传递&#xff08;P…

Python之jieba分词相关介绍

1.jieba分词的安装 直接在cmd窗口当中pip install即可 2.jieba分词的介绍 jieba分词是目前比较好的中文分词组件之一&#xff0c;jieba分词支持三种模式的分词(精确模式、全模式、搜索引擎模式)&#xff0c;并且支持自定义词典(这一点在特定的领域很重要&#xff0c;有时候…

C++(20):list通过erase, erase_if删除元素

C++20前,使用成员函数erase删除元素,与vector的方法一致: iterator erase( iterator pos ); iterator erase( iterator first, iterator last ); 1.通过迭代器删除指定位置元素 需要说明的是,删除元素后,迭代器会失效,可以通过erase返回下一个有效的迭代器 #include &…

SpringBoot使用MockMVC单元测试Controller

对模块进行集成测试时&#xff0c;希望能够通过输入URL对Controller进行测试&#xff0c;如果通过启动服务器&#xff0c;建立http client进行测试&#xff0c;这样会使得测试变得很麻烦&#xff0c;比如启动速度慢&#xff0c;测试验证不方便&#xff0c;依赖网络环境等&#…

GitHub项目推荐-incubator

项目地址 Github地址&#xff1a;GitHub - apache/incubator-anser 官网&#xff1a;Apache Answer | Free Open-source Q&A Platform 项目简述 这是Apache的一个开源在线论坛&#xff0c;也可以部署成为一个自有的QA知识库。项目主要使用了Go和Typescript来开发&#…

【MATLAB源码-第109期】基于matlab的哈里斯鹰优化算发(HHO)机器人栅格路径规划,输出做短路径图和适应度曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 哈里斯鹰优化算法&#xff08;Harris Hawk Optimization, HHO&#xff09;是一种受自然界捕食行为启发的优化算法。它基于哈里斯鹰的捕猎策略和行为模式&#xff0c;主要用于解决各种复杂的优化问题。这个算法的核心特征在于…

层叠布局(Stack)

目录 1、概述 2、开发布局 3、对齐方式 3.1、TopStart 3.2、Top 3.3、TopEnd 3.4、Start 3.5、Center 3.6、End 3.7、BottomStart 3.8、Bottom 3.9、BottomEnd 4、Z序控制 5、场景示例 1、概述 层叠布局&#xff08;StackLayout&#xff09;用于在屏幕上预留一…