C#基础 延迟加载介绍与实例

延迟加载(lazy loading) 设计模式是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据(读取属性值)的时候,才真正执行数据加载操作.

为了便于理解, 我们来建立一个场景, 假设我们要构造一个Hero(英雄) 类, 每个Hero 有自己的名字和(SpecialSkill)特殊技能.
建模
这是一种建立的方法:


代码如下:

public class Hero
{
    public string FullName { get; set; }
    public string Name { get; set; }
    public SpecialSkill Skill{ get; set; }

public Hero(string name)
    {
        Name = name;
        FullName = "Super " + name;
        Skill = new SpecialSkill(name);
    }
}
public class SpecialSkill
{
    public int Power { get; set; }
    public string SkillName { get; set; }
    public int StrengthSpent { get; set; }
    public SpecialSkill(string name)
    {
        Console.WriteLine("loading special skill .....");
        Power = name.Length;
        StrengthSpent = name.Length * 3;
        SkillName = name + " Blazing";
        Console.WriteLine(SkillName + ",... this's what makes a legend!");
    }
}
class Program
{
    static void Main(string[] args)
    {
        Hero hero = new Hero("wukong");           
        Console.WriteLine("\n\n.......................Press Enter to continue.......................\n\n");
        Console.Read();
        Console.WriteLine("Hero's special skill: " + hero.Skill.SkillName);
        Console.Read();
        Console.Read();
    }
}

运行程序后输出如下, 这个例子非常的容易理解, 结果也是显然的.

它的缺点是, 当运行Hero 构造函数的时候, SpecialSkill 的所有属性都已经加载了. 如果我们只想获取这个Hero 的FullName, 我们也加载了SpecialSkill 所有值.

属性的加载延迟
在没有Lazy<T> 以前我们可以这样做:


代码如下:

public class Hero
 {
     public string FullName { get; set; }
     public string Name { get; set; }
     private SpecialSkill skill;
     public SpecialSkill Skill
     {
         get { return skill ?? (skill = new SpecialSkill(Name)); }
     }
     public Hero(string name)
     {
         Name = name;
         FullName = "Super " + name;

}
 }

即: 修改属性SpecialSkill的加载方法. 那么当我们再运行程序时, 得到的输出就是:

非常好! 这就是我们要的效果, 这样可以让系统更加的有效率.

Lazy<T>
当net framework 引入了Lazy<T> 类后, 我们也可以使用它来实现:


代码如下:

public class Hero
{
    public string FullName { get; set; }
    public string Name { get; set; }

private readonly Lazy<SpecialSkill> skill;
    public SpecialSkill Skill
    {
        get { return skill.Value; }
    }

public Hero(string name)
    {
        Name = name;
        FullName = "Super " + name;

skill = new Lazy<SpecialSkill>(() => new SpecialSkill(name));
    }
}

Lazy<T>提供对延迟初始化的支持。而 Lazy<T> 中的一个属性 Value, 则是获取当前 Lazy<T> 实例的延迟初始化值。

Lazy<T>的优势
那么既然我们已经可以用属性缓存的方法实现, 为什么还要引入Lazy<T> ?
至少Lazy<T> 有以下几点优势:
它具有 LazyThreadSafetyMode, 但是我们一般不使用它, 除非是很关键的情况下(在此略去181个字)
它使属性的定义行更加简单
从语义上来讲, 它更加明确, 更加具有可读性
它允许null为有效值

(0)

相关推荐

  • C#中使用迭代器处理等待任务

     介绍 可能你已经阅读 C#5 关于 async 和 await 关键字以及它们如何帮助简化异步编程的,可惜的是在升级VS2010后短短两年时间,任然没有准备好升级到VS2012,在VS2010和C#4中不能使用异步关键字,你可能会想 "如果我能在VS 2010中写看起来同步的方法,但异步执行.我的代码会更清晰." 看完这篇文章后,您将能够做到这一点.我们将开发一个小的基础结构代码,让我们写"看起来同步的方法,但异步执行"的方法,这个VS2012 异步关键字一样,

  • C#中Linq延迟查询的例子

    提出问题 下面所给代码编译时正常,但是执行时会出错,请指出程序在执行时能够执行到编号为(1)(2)(3)的代码行中的哪一行. using System; using System.Collections.Generic; using System.Linq; namespace DeferredExecutionExp { class Program { static void Main(string[] args) { List<Student> studentList = new List

  • C#特性 迭代器(下) yield以及流的延迟计算

    从0遍历到20(不包括20),输出遍历到的每个元素,并将大于2的所有数字放到一个IEnumerable<int>中返回 解答1:(我以前经常这样做) static IEnumerable<int> WithNoYield() { IList<int> list = new List<int>(); for (int i = 0; i < 20; i++) { Console.WriteLine(i.ToString()); if(i > 2) l

  • C#实现程序等待延迟执行的方法

    本文实例讲述了C#实现程序等待延迟执行的方法.分享给大家供大家参考.具体如下: [System.Runtime.InteropServices.DllImport("kernel32.dll")] static extern uint GetTickCount(); /// <summary> /// 程序等待延迟执行 /// </summary> /// <param name="ms"></param> stati

  • C#随机设置900-1100毫秒延迟的方法

    本文实例讲述了C#随机设置900-1100毫秒延迟的方法.分享给大家供大家参考.具体如下: using System; using System.Threading; ///<summary> /// A time delay of 900..1100 milliseconds ///</summary> namespace RobvanderWoude { class WaitASecond { static void Main( string[] args ) { // Cho

  • c#3.0实现延迟赋值示例

    延迟赋值主要有两点: 1.一个参数可能或可能没被赋值. 2.一个参数在一个函数中每次使用时可能被赋值. 如下面的这种情况: 复制代码 代码如下: int Add(int x, int y){    return (2 + 1) + (1);} 使用Func<T>,我们轻松实现,看代码: 复制代码 代码如下: /// <summary>/// LazyExpression/// </summary>/// <typeparam name="T"&

  • C#基础 延迟加载介绍与实例

    延迟加载(lazy loading) 设计模式是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据(读取属性值)的时候,才真正执行数据加载操作. 为了便于理解, 我们来建立一个场景, 假设我们要构造一个Hero(英雄) 类, 每个Hero 有自己的名字和(SpecialSkill)特殊技能.建模这是一种建立的方法: 复制代码 代码如下: public class Hero{    public string FullName { get; set; }    public s

  • Linux基础命令last 命令实例详解

    Linux last命令用于显示系统开机以来获是从每月初登入者的讯息. 使用权限:所有使用者. last 显示以前登录过的用户信息,last指令会搜索/var/log/wtmp文件(或者是经过-f选项指定的文件),然后列出文件中所有的用户信息.如果执行last指令时提示"last /var/log/wtmp∶ NO such file or directory",则需要使用指令touch /var/log/wtmp手工创建此文件 lastb指令用来显示登录失败的用户信息,其用法和las

  • Python简单基础小程序的实例代码

    1 九九乘法表 for i in range(9):#从0循环到8 i += 1#等价于 i = i+1 for j in range(i):#从0循环到i j += 1 print(j,'*',i,'=',i*j,end = ' ',sep='') # end默认在结尾输出换行,将它改成空格 sep 默认 j,'*',i,'=',i*j 各元素输出中间会有空格 print()#这里作用是输出换行符 i = 1 while i <= 9: j = 1 while j <= i: print(&

  • JAVA中Context的详细介绍和实例分析

    最熟悉的陌生人--Context 刚刚学android或者js等,都会看见这个频繁的字眼--Context. 意为"上下文". 本文主要记述,Context到底是什么.如何理解Context.一个APP可以有几个Context.Context能干啥.Context的作用域.获取Context.全局获取Context技巧. 思考: Java:万物皆对象.Flutter:万物皆组件. 俗语:"没对象吗?自己new一个啊~" 既然大多数情况可以new一个实例,那么,我们在

  • R语言基础统计方法图文实例讲解

    tidyr > tdata <- data.frame(names=rownames(tdata),tdata)行名作为第一列 > gather(tdata,key="Key",value="Value",cyl:disp,mpg)创key列和value列,cyl和disp放在一列中 -号减去不需要转换的列 > spread(gdata,key="Key",value="Value") 根据value将

  • C# 最基础知识介绍--多态

    目录 一.C# 多态性 二.静态多态性 三.函数重载 四.C# 运算符重载 1.运算符重载的实现 2.可重载和不可重载运算符 五.动态多态性 前言:

  • Python类和对象基础入门介绍

    目录 视频 Python 类和对象 创建和使用类 根据类创建实例 视频 观看视频 Python 类和对象 面向对象编程是编写表示现实世界中的事物和情景的类,并基于这些类来创建对象. 编写类时,你定义一大类对象都有的通用行为.基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性.使用面向对象编程可模拟现实情景,其逼真程度达到了令你惊讶的地步. 根据类来创建对象被称为实例化,这是能够使用类的实例. 面向对象最重要的概念就是类(Class)和实例(Instance),

  • Vue组件基础操作介绍

    目录 一.组件 二.组件的创建 三.组件中的data 四.组件中的methods 一.组件 组件是vue的重要的特征之一,可以扩展html的功能,也可以封装代码实现重复使用. 二.组件的创建 1. 非脚手架方式下创建 ​ 第一步:使用Vue.extend创建组件 ​ 第二步:使用Vue.component注册组件 ​ 第三步:在html页面中使用组件 <div id="app"> <my-com></my-com> <!-- 使用组件:名称之间

  • linux文件搜索及其它基础命令介绍(3)

    1.linux中包含大量的文件,对于文件查找,linux提供了find命令. find是一个非常有效的工具,它可以遍历目标目录甚至整个文件系统来查找某些文件或目录: find [path...] [expression] 其中expression包括三种:options.tests和actions.多个表达式之间被操作符分隔,当操作符被省略时,表示使用了默认操作符-and. 当表达式中不包含任何actions时,默认使用-print,也就是打印出搜索到的所有文件,用换行分隔. 其实可以将三种表达

  • linux文本过滤grep基础命令介绍(5)

    在linux中经常需要对文本或输出内容进行过滤,最常用的过滤命令是grep grep [OPTIONS] PATTERN [FILE...] grep按行检索输入的每一行,如果输入行包含模式PATTERN,则输出这一行.这里的PATTERN是正则表达式(参考前一篇,本文将结合grep一同举例). 输出文件/etc/passwd中包含root的行: [root@centos7 temp]# grep root /etc/passwd root:x:0:0:root:/root:/bin/bash

随机推荐