【.NET Core】Lazy<T> 实现延迟加载详解

news2024/9/22 11:23:06

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

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

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

相关文章

语义分割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&#xff0c;平均…

山西电力市场日前价格预测【2024-01-13】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2024-01-13&#xff09;山西电力市场全天平均日前电价为231.81元/MWh。其中&#xff0c;最高日前电价为345.71元/MWh&#xff0c;预计出现在00:15。最低日前电价为0.00元/MWh&#xff0c;预计出…

大模型实战笔记04——XTuner 大模型单卡低成本微调实战

大模型实战笔记04——XTuner 大模型单卡低成本微调实战 1、Finetune简介 2、XTuner 3、8GB显存玩转LLM 4、动手实战环节 注&#xff1a; 笔记内容均为截图 课程视频地址&#xff1a;https://www.bilibili.com/video/BV1yK4y1B75J/?spm_id_from333.788&vd_source2882acf…

行为型设计模式——备忘录模式

备忘录模式 备忘录模式提供了一种状态恢复的实现机制&#xff0c;使得用户可以方便地回到一个特定的历史步骤&#xff0c;当新的状态无效或者存在问题时&#xff0c;可以使用暂时存储起来的备忘录将状态复原&#xff0c;很多软件都提供了撤销&#xff08;Undo&#xff09;操作…

计算机网络NCEPU复习资料

目录 一&#xff0e;概述&#xff1a; 计算机网络组成&#xff1a; 计算机网络分类&#xff1a; 计算机网络体系结构&#xff1a; C/S架构与P2P架构区别&#xff1a; OSI开放式系统互连参考模型&#xff1a; OSI开放式系统互连参考模型 相关协议&#xff1a; 五层协议网…

【Vue2】一个数组按时间分割为【今年】和【往年】俩个数组

一. 需求 后端返回一个数组&#xff0c;前端按时间维度将该数组的分割为【今年】和【往年】俩个数组后端返回的数组格式如下 timeList:[{id:1,billTime:"2024-01-10",createTime:"2024-01-10 00:00:00",status:0},{id:2,billTime:"2022-05-25"…

(收藏)数据治理:一文讲透数据安全

数据治理&#xff1a;一文讲透数据安全 数据安全是数据治理的核心内容之一&#xff0c;随着数据治理的深入&#xff0c;我不断的碰到数据安全中的金发姑娘问题&#xff08;指安全和效率的平衡&#xff09;。 DAMA说&#xff0c;降低风险和促进业务增长是数据安全活动的主要…

详解Java信号量-Semaphore

第1章&#xff1a;引言 大家好&#xff0c;我是小黑。今天&#xff0c;咱们一起来深入探讨一下Semaphore。在Java中&#xff0c;正确地管理并发是一件既挑战又有趣的事情。当谈到并发控制&#xff0c;大家可能首先想到的是synchronized关键字或者是ReentrantLock。但其实&…

Open3D 获取点云坐标最值(17)

Open3D 获取点云坐标最值(17) 一、算法介绍二、算法实现1.代码2.结果人生天地间,忽如远行客 一、算法介绍 快速获取点云块,沿着 x y z 各方向的坐标最值,这些在点云处理中的应用范围是如此广泛,这也是点云最常被用到的关键信息,后续的很多算法都会设置到这一处理方法。…

迈入AI智能时代!ChatGPT国内版免费AI助手工具 peropure·AI正式上线 一个想法写一首歌?这事AI还真能干!

号外&#xff01;前几天推荐的Peropure.Ai迎来升级&#xff0c;现已支持联网模式&#xff0c;回答更新更准&#xff0c;欢迎注册体验&#xff1a; https://sourl.cn/5T74Hu 相信很多人都有过这样的想法&#xff0c;有没有一首歌能表达自己此时此刻的心情&#xff1a; 当你在深…

【LabVIEW FPGA入门】模拟输入和模拟输出

1.简单模拟输入和输出测试 1.打开项目&#xff0c;在FPGA终端下面新建一个VI 2.本示例以模拟输入卡和模拟输出卡同时举例。 3.新建一个VI编写程序&#xff0c;同时将卡1的输出连接到卡2的输入使用物理连线。 4.编译并运行程序&#xff0c;观察是否能从通道中采集和输出信号。 5…

计算机缺失msvcr100.dll如何修复?分享五种实测靠谱的方法

在计算机系统的日常运行与维护过程中&#xff0c;我们可能会遇到一种特定的故障场景&#xff0c;即系统中关键性动态链接库文件msvcr100.dll的丢失。msvcr100.dll是Microsoft Visual C Redistributable Package的一部分&#xff0c;对于许多基于Windows的应用程序来说&#xff…

【动态规划】LeetCode-42. 接雨水

42. 接雨水。 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1…

GPUMD分子动力学模拟-学习与实践

GPUMD分子动力学模拟-学习与实践 【20220813-樊哲勇 |基于GPUMD程序包的机器学习势和分子动力学模拟】 https://www.bilibili.com/video/BV1cd4y1Z7zi?share_sourcecopy_web 纯GPU下的MD分子模型系统软件 https://github.com/brucefan1983/GPUMD 跟GPUMD对接的一些python程…

绘制几何图形(Shape)

目录 1、创建绘制组件 2、形状视口viewport 3、自定义样式 4、场景示例 绘制组件用于在页面绘制图形&#xff0c;Shape组件是绘制组件的父组件&#xff0c;父组件中会描述所有绘制组件均支持的通用属性。具体用法请参考Shape。 1、创建绘制组件 绘制组件可以由以下两种形式…

Servlet-Request

一、预览 在上一篇Servlet体系结构中&#xff0c;我们初步了解了怎么快速本篇将介绍Servlet中请求Request的相关内容&#xff0c;包括Request的体系结构&#xff0c;Request常用API。 二、Request体系结构 我们注意到我们定义的Servlet类若实现Servlet接口时&#xff0c;请求…

第十七周周报

文章目录 摘要目标检测锚框交并比NMS 非极大值抑制输出 文献阅读&#xff1a;SMPL: A Skinned Multi-Person Linear ModelIntroductionRelated WorkModel FormulationTraining评估动态SMPL讨论结论 总结 摘要 本周看了三维人体重建的领域&#xff0c;看了一篇SMPL的文章&#…

C++算法学习心得五.二叉树(4)

1.二叉搜索树中的插入操作&#xff08;701题&#xff09; 题目描述&#xff1a;给定二叉搜索树&#xff08;BST&#xff09;的根节点和要插入树中的值&#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据保证&#xff0c;新值和原始二叉搜索树中的任意…

Go 知多少?

作为一名已接触过其他语言的开发&#xff0c;再去学习一门新语言可比之前轻松不少&#xff0c; 语言之间存在很多相似点&#xff0c;但是新语言也有自己的不同点&#xff0c;通常我会先了解它与其他语言常遇到的不同点有哪些&#xff0c; 使自己先能够上手编写基础程序&#…

【LabVIEW FPGA入门】LabVIEW FPGA实现I2S解码器

该示例演示了如何使用 LabVIEW FPGA 解码 IS 信号。该代码可用于大多数支持高速数字输入的LabVIEW FPGA 目标&#xff08;例如R 系列、CompactRIO&#xff09;。IS 用于对系统和组件内的数字音频数据进行编码。例如&#xff0c;MP3 播放器或 DVD 播放器内部的数字音频通常使用 …