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

这篇具有很好参考价值的文章主要介绍了【.NET Core】Lazy<T> 实现延迟加载详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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


【.NET Core】Lazy<T> 实现延迟加载详解,.Net Core,.netcore,redis,linq,c#,asp.net,.net

一、概述

延迟初始化是一种将对象的创建延迟到第一次需要用时的技术。简而言之,就是对象的初始化发生在第一次需要调用的时候执行。通常所说的延迟初始化和延迟实例化的意思是相同。通过使用延迟基础,可以避免应用程序不必要的计算和内存消耗。

从.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 属性此后会返回已分配给该属性的新值。文章来源地址https://www.toymoban.com/news/detail-811588.html

到了这里,关于【.NET Core】Lazy<T> 实现延迟加载详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【.NET Core】反射(Reflection)详解(三)

    反射提供了对已封装的程序集、模型和类型的对象一种动态访问方法。反射包含动态加载程序集的Assembly类、程序集中模块访问的Module类、对类信息Type类、构造函数信息ConstructorInfo类、方法信息MethodInfo类、字段信息FieldInfo类、事件信息EventInfo类、属性信息PropertyInfo类、参数信

    2024年02月03日
    浏览(31)
  • 2.1 .net 8 ASP.NET Core Web API - Controller详解

    书接上回,上节我们留了几个问题,即: 1、接口Hello的名字究竟怎么来的? 2、我们如果想把接口改成其他的名称,应该怎么做? 3、我们继承ControllerBase,以及[Route(“[controller]”)]属性,又是分别起到什么作用? 需要解决以上几个问题,我们就要继续深入研究Controller相关的

    2024年02月20日
    浏览(47)
  • 【.NET Core】 多线程之(Thread)详解

    线程 被定义为程序的执行路径。每个线程都定义了一个独特的控制流。如果您的应用程序涉及复杂且耗时的操作,那么设置不同的线程执行路径往往事半功倍,让每个线程执行特定的工作任务。 线程是一个 轻量级进程 。一个使用线程的常见实例是操作系统中并行编程的实现

    2024年01月20日
    浏览(38)
  • 【c#,.NET】Entity Framework Core基础详解

    目录   一、EF Core概述 1.1 什么是ORM?  1.2 EF Core的性能怎么样  二、EF Core入门 2.1 什么是Migration数据库迁移: 2.2  EF Core数据的增删改查 2.2.1 增加数据 2.2.2 查询数据  2.2.3 修改和删除数据 三、EF Core的实体类配置 3.1 约定大于配置 3.2 EF Core两种配置方式 3.2.1 Data Annotation 3.2.2 

    2024年02月04日
    浏览(62)
  • Taurus .Net Core 微服务开源框架:Admin 插件【3】 - 指标统计管理 -【API、Redis、MemCache】

    继上篇:Taurus .Net Core 微服务开源框架:Admin 插件【2】 - 系统环境信息管理 本篇继续介绍下一个内容: 界面图如下: 该页面默认呈现API访问次数的统计,由于要显示的数据列有点多,24小时,因此用了全屏显示。 同时提供快捷切换显示选项:昨天与今天。 如果需要查询其余

    2024年02月11日
    浏览(40)
  • 【一文详解】知识分享:(ASP.Net Core基础学习及快速入门)

    .Net .NET是微软的一个开发平台,这个平台的一大特点就是跨语言性,不管是什么语言,c、c++、c#、F#、J#、vb等语言都可以用这个平台合作开发; .NET,它是微软创建的一个用于构建多种不同类型的应用程序的开发人员平台。 .NET 是一个广泛的术语,用于描述整个 Microsoft 的软件

    2024年02月01日
    浏览(63)
  • 详解ASP.NET Core 在 IIS 下的两种部署模式

    KestrelServer最大的优势体现在它的跨平台的能力,如果ASP.NET CORE应用只需要部署在Windows环境下,IIS也是不错的选择。ASP.NET CORE应用针对IIS具有两种部署模式,它们都依赖于一个IIS针对ASP.NET CORE Core的扩展模块。 IIS其实也是按照管道的方式来处理请求的,但是IIS管道和ASP.NET CO

    2024年02月10日
    浏览(49)
  • .NET Core 实现Excel的导入导出

    目录 前言 NPOI简介 一、安装相对应的程序包 1.1、在 “管理NuGet程序包” 中的浏览搜索:“NPOI” 二、新建Excel帮助类 三、调用 3.1、增加一个“keywords”模型类,用作导出 3.2、添加一个控制器 3.3、编写导入导出的控制器代码 3.3.1、重写“Close”函数 3.3.2、添加控制器代码 3.

    2024年02月08日
    浏览(35)
  • MinIO (五) .net core实现分片上传

    开发环境 Win11 vs2022 appsettings.json添加配置项 注入代码 接下来是后端进行分片上传的代码示例,有两个,第一个是从官方考下来的代码示例,第二个是自己整理后的代码示例。 从官方考下来的代码示例 整理后的后端进行分片上传

    2024年02月03日
    浏览(42)
  • .Net Core 使用 AspNetCoreRateLimit 实现限流

    上一篇文章介绍过ASP.NET Core 的 Web Api 实现限流 中间件-CSDN博客 使用.NET 7 自带的中间件  Microsoft.AspNetCore.RateLimiting  可以实现简单的Api限流,但是这个.NET 7以后才集成的中间件,如果你使用的是早期版本的.NET,可以使用第三方库AspNetCoreRateLimit实现Api限流。 AspNetCoreRateLimit 是

    2024年01月18日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包