【.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 method
                   true);                          // double locks
      public 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 属性此后会返回已分配给该属性的新值。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

我们做了个写论文解读的agent

已经2024年了&#xff0c;该出现一个论文解读AI Agent了。 尽管我们公司的主营业务不是做这块的&#xff0c;但&#xff0c;我们还是顺手做了这样一个agent&#xff0c;因为——我们公司的算法同学也需要刷论文啊喂&#xff0c; 而且我们也经常人工写论文解读嘛&#xff0c;所…

深入分析 Spring 中 Bean 名称的加载机制

目录 前言 通过前文&#xff1a;《深入分析-Spring BeanDefinition构造元信息》一文我们可以了解到&#xff1a;Spring Framework共有三种方式可以定义Bean&#xff0c;分别为&#xff1a;XML配置文件、注解、Java配置类&#xff0c; 从Spring Framework 3.0&#xff08;2019年…

node-sass@4.7.2 postinstall: `node scripts/build.js`

Can‘t find Python executable “D:\Python36\python.EXE“, you can set the PYTHON env variable.-CSDN博客 gyp ERR! build error gyp ERR! stack Error: C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe failed with exit code: 1 gyp ERR! stack at Chil…

解密Mybatis-Plus:优雅简化你的数据访问层!

目录 1、引言 2、什么是Mybatis-Plus 3、Mybatis-Plus的特点和优势 4、安装和配置Mybatis-Plus 5、使用Mybatis-Plus进行数据库操作 6、Mybatis-Plus的高级功能 7、Mybatis-Plus的扩展和插件 8、与Spring Boot集成 9、结语 1、引言 Mybatis-Plus是一个强大而优雅的Jav…

阿里云ingress配置时间超时的参数

一、背景 在使用阿里云k8s集群的时候&#xff0c;内网API网关&#xff0c;刚开始是用的是Nginx&#xff0c;后面又搭建了ingress。 区别于nginx配置&#xff0c;ingress又该怎么设置参数呢&#xff1f;比如http超时时间等等。 本文会先梳理nginx是如何配置&#xff0c;再对比…

Elasticsearch:是时候离开了! - 在 Elasticsearch 文档上使用 TTL

作者&#xff1a;来自 Elastic David Pilato 想象一下&#xff0c;圣诞老人必须向世界上所有的孩子们分发礼物。 他有很多工作要做&#xff0c;他需要保持高效。 他有一份所有孩子的名单&#xff0c;并且知道他们住在哪里。 他很可能会将礼物按区域分组&#xff0c;然后再交付。…

Qt QSQlite数据库插入字符串中存在单个双引号或单个单引号解决方案

1. 前言 当进行数据库写入或更新时&#xff0c;有时会遇到存在字符串中包含单个双引号或者单引号。 2. 单引号和双引号""作用 在数据库中&#xff0c;字符串常量时需要用一对英文单引号或英文双引号""将字符串常量括起来。 比如&#xff1a; select * …

stable-diffusion 学习笔记

从效果看Stable Diffusion中的采样方法 参考&#xff1a;Ai 绘图日常 篇二&#xff1a;从效果看Stable Diffusion中的采样方法_软件应用_什么值得买 大概示例&#xff1a;

Java Web课设——个人博客(双端系统)

项目演示 先看看演示视频吧 演示图 简单介绍 个人博客管理系统采用Springboot2.4.5框架开发&#xff0c;是标准的MVC模式&#xff0c;将这个系统划分为View层、Controller层、Service层、DAO层和持久层五层。其中&#xff0c;Spring MVC负责请求的转发和视图管理&#xff0c;S…

蓝桥杯单片机组备赛——数码管动态显示

✨文章内容会不断优化&#xff0c;如果你感兴趣的话&#xff0c;欢迎点藏收藏关注我哟 &#x1f9e8;如果文章有哪里看不懂的欢迎评论区或私信留言&#xff0c;我会及时回复的 ⏰如果文章出现错误&#xff0c;欢迎指正&#xff0c;看到后我会马上改正 文章目录 一、动态显示原理…

Java SE入门及基础(10)

switch选择结构 1. 概念 switch 表示开关的意思&#xff0c;为了帮助理解&#xff0c;下面以线路为例&#xff0c;进行解释说明 上图中表示一条带有多个开关的线路&#xff0c;当开关打开时&#xff0c;该开关所控制的灯即被点亮。 2. 语法规则 switch ( 表达式 ){ //…

SECS/GEM的变量SVID是什么?JAVA SECS通信 JAVA与SECS集成资料大全JAVA开发SECS快速入门资料

Java与SECS基础通信 Java实现SECS指令S2F17获取时间 Java实现SECS指令 S10F3 终端单个显示例子 工艺配方管理S7FX Java实现SECS指令 S5F1报警/取消报警上传 实例源码及DEMO请查阅 变量可以是设备的状态信息 定义&#xff1a; 此功能允许主机查询设备数据变量&#x…

C#基于ScottPlot进行可视化

前言 上一篇文章跟大家分享了用NumSharp实现简单的线性回归&#xff0c;但是没有进行可视化&#xff0c;可能对拟合的过程没有直观的感受&#xff0c;因此今天跟大家介绍一下使用C#基于Scottplot进行可视化&#xff0c;当然Python的代码&#xff0c;我也会同步进行可视化。 P…

虚幻引擎nDisplay教程:如何同步nDisplay节点与Switchboard + Helix Core

对于使用大型LED屏幕进行拍摄的虚拟制作团队来说&#xff0c;虚幻&#xff08;Unreal&#xff09;的nDisplay是一个重要的工具。但是&#xff0c;在nDisplay中将正确版本的文件发送到每个节点会非常耗时。立即阅读本文&#xff0c;您将了解到如何使用Perforce Helix Core版本控…

【b站咸虾米】新课uniapp零基础入门到项目打包(微信小程序/H5/vue/安卓apk)全掌握

课程地址&#xff1a;【新课uniapp零基础入门到项目打包&#xff08;微信小程序/H5/vue/安卓apk&#xff09;全掌握】 https://www.bilibili.com/video/BV1mT411K7nW/?p12&share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 三、vue语法 继续回到官…

Python之jieba分词相关介绍

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

VMware workstation搭建与安装AlmaLinux-9.2虚拟机

VMware workstation搭建与安装AlmaLinux-9.2虚拟机 适用于需要在VMware workstation平台安装AlmaLinux-9.2&#xff08;最小化安装、无图形化界面&#xff09;虚拟机。 1. 安装准备 1.1 安装平台 Windows 11 1.2. 软件信息 软件名称软件版本安装路径VMware-workstation 1…

【前端素材】bootstrap5实现美食餐饮网站RegFood

一、需求分析 美食餐饮网站是指专门提供关于美食和餐饮的信息、服务和资源的在线平台。这类网站通常提供以下功能&#xff1a; 餐厅搜索和预订&#xff1a;用户可以在网站上搜索附近的餐厅&#xff0c;并预订桌位。网站会提供餐厅的详细信息&#xff0c;包括菜单、地址、电话号…

Jmeter 性能-监控服务器

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

JDK介绍

JDK(Java Development Kit)是Sun Microsystems针对Java开发员的产品。自从Java推出以来&#xff0c;JDK已经成为使用最广泛的Java SDK&#xff08;Software development kit&#xff09;&#xff0c;JDK是一个写Java的applet和应用程序的程序开发环境。它由一个处于操作系统层之…