.NET泛型04,使用Lazy<T>实现延迟加载
对于一些"大对象"的创建,我们常常希望延迟加载,即在需要的时候再创建对象实例。现在Lazy<T>很好地支持了这一特点。主要包括:
没有Lazy<T>之前
在没有Lazy<T>之前,我们通过如下方式实现延迟加载。
public class LazySinleton
{
private LazySingleton()
{}
public static LazySingleton Instance
{
get
{
return Lazy.data;
}
}
private class Lazy
{
static Lazy()
{}
internal static readonly LazySingleton data = new LazySingleton();
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
以上
● 通过私有构造函数屏蔽了LazySingleton类通过构造函数创建的方式
● 私有嵌套类Lazy的data字段负责提供一个LazySingleton的实例
● 只能通过LazySingleton的属性Instance,才能拿到内部类Lazy.data所代表的实例
Lazy<T>实例
先看Lazy<T>的定义:
public class Lazy<T>
{
public Lazy();
public Lazy(bool isThreadSafe);
public Lazy(Func<T> valueFactory);
public Lazy(LazyThreadSafeMode mode);
public Lazy(Func<T> valueFactory, bool isThreadSafe);
public Lazy(Funct<T> valueFactory, LazyThreadSafetyMode mode); public bool IsValueCreated{get;}
public T Value {get;}
public override string ToStirng();
}
通过Lazy<T>的构造函数重载创建对象,再通过体现延迟加载的Value属性来实现对象的创建,并获取对象实例。
public class SomeClass
{
public int ID{get;set;}
} Lazy<SomeClass> temp = new Lazy<SomeClass>();
Console.WriteLine(temp.Value.ID);
以上,只适用于没有构造函数的情况,如果有构造函数如何处理呢?
--使用public Lazy(Func<T> valueFactory),通过委托创建对象
pubic class SomeClass
{
public int ID{get;set;}
public SomeClass(int id)
{
this.ID = id;
}
} Lazy<SomeClass> temp = new Lazy<SomeClass>(() => new Big(100));
Console.WriteLine(temp.Value.ID);
延迟加载的本质
创建自定义延迟加载类。
public class MyLazy<T>
{
private volatile object boxed; //volatile说明在多线程状况下,也可以修改该字段
private Func<T> valueFactory; //委托,用来生产T对象实例 static MyLazy(){}
public MyLazy(){} public MyLazy(Func<T> valueFactory)
{
this.valueFactory = valueFactory;
} public T Value
{
get
{
Boxed boxed = null;
if (this.boxed != null)
{
boxed = this.boxed as Boxed;
if (boxed != null)
{
return boxed.value;
}
}
return this.Init();
}
} //初始化对象实例
private T Init()
{
Boxed boxed = null;
if (this.boxed == null)
{
boxed = this.CreateValue();
this.boxed = boxed;
}
return boxed.value;
} //创建内部类实例
private Boxed CreateValue()
{
//如果创建对象实例的委托valueFactory存在
if (this.valueFactory != null)
{
//就通过委托生成对象实例
return new Boxed(this.valueFactory());
}
else
{
//否则,通过反射生成对象实例
return new Boxed((T)Activator.CreateInstance(typeof(T)));
}
} //内部嵌套类,通过构造函数对其字段赋值
private class Boxed
{
internal T value;
internal Boxed(T value)
{
this.value = value;
}
}
}
自定义带构造函数的类。
public class Big
{
public int ID { get; set; }
public Big(int id)
{
this.ID = id;
}
}
自定义创建对象实例的工厂类。
public class BigFactory
{
public static Big Build()
{
return new Big(10);
}
}
客户端调用。
class Program
{
static void Main(string[] args)
{
MyLazy<Big> temp = new MyLazy<Big>(() => BigFactory.Build());
Console.WriteLine(temp.Value.ID);
Console.ReadKey();
}
}
延迟加载的本质大致是:
● 由延迟加载类的内部嵌套类产生对象实例
● 再通过延迟加载类的某个属性来延迟获取对象实例,而对象实例是通过委托等方式创建的
参考资料:
《你必须知道的.NET(第2版)》,作者王涛。
".NET泛型"系列包括:
.NET泛型01,为什么需要泛型,泛型基本语法
.NET泛型02,泛型的使用
.NET泛型03,泛型类型的转换,协变和逆变
.NET泛型04,使用Lazy<T>实现延迟加载
.NET泛型04,使用Lazy<T>实现延迟加载的更多相关文章
- Lazy Load 图片延迟加载(转)
jQuery Lazy Load 图片延迟加载来源 基于 jQuery 的图片延迟加载插件,在用户滚动页面到图片之后才进行加载. 对于有较多的图片的网页,使用图片延迟加载,能有效的提高页面加载速度. ...
- jQuery Lazy Load 图片延迟加载
基于 jQuery 的图片延迟加载插件,在用户滚动页面到图片之后才进行加载. 对于有较多的图片的网页,使用图片延迟加载,能有效的提高页面加载速度. 版本: jQuery v1.4.4+ jQuery ...
- lazy load 图片延迟加载 跟随滚动条
http://plugins.jquery.com/lazyload/ Jquery.LazyLoad.js插件参数详解: 1,用图片提前占位 placeholder : "img/grey ...
- .NET泛型03,泛型类型的转换,协变和逆变
协变(Convariant)和逆变(Contravariant)的出现,使数组.委托.泛型类型的隐式转换变得可能. 子类转换成基类,称之为协变:基类转换成子类,称之为逆变..NET4.0以来,支持了泛 ...
- .NET泛型02,泛型的使用
在" .NET泛型01,为什么需要泛型,泛型基本语法"中,了解了泛型的基本概念,本篇偏重于泛型的使用.主要包括: ■ 泛型方法重载需要注意的问题■ 泛型的类型推断■ 泛型方法也可以 ...
- .NET泛型01,为什么需要泛型,泛型基本语法
.NET泛型或许是借鉴于C++泛型模版,借助它可以实现对类型的抽象化.泛型处理,实现了类型和方法之间的解耦.一个最经典的运用是在三层架构中,针对不同的领域模型,在基接口.基类中实现针对各个领域模型的泛 ...
- jQuery延迟加载插件(Lazy Load)详解
最 新版本的Lazy Load并不能替代你的网页.即便你使用JavaScript移除了图片的src属性,有些现代的浏览器仍然会加载图片.现在你必须修改你的html代 码,使用占位图片作为img标签的s ...
- 使用Lazy<T>实现对客户订单的延迟加载
"延迟加载"是指在需要的时候再加载数据.比如获得一个Customer信息,并不会把该Customer的Orders信息一下加载出来,当需要显示Orders的时候再加载.简单来说,就 ...
- java:Hibernate框架4(延迟加载(lazy),抓取(fetch),一级缓存,get,load,list,iterate,clear,evict,flush,二级缓存,注解,乐观锁和悲观锁,两者的比较)
1.延时加载和抓取: hibernate.cfg.xml: <?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-co ...
随机推荐
- jquery中获取iframe的id的方法:
jquery中获取iframe的id的方法: var frameId = window.frameElement && window.frameElement.id || ''; al ...
- Python *args **kw
当函数的参数不确定时,可以使用*args 和**kwargs,*args 没有key值,**kwargs有key值. *args def fun_var_args(farg, *args): prin ...
- gluster学习(二)
GlusterFS卷管理 一.卷基本选项设置 1. 调整高速缓存大小 gluster volume set test-volume performance.cache-size 256MB 2. 详细 ...
- htm5本地存储方案——websql的封装
一.websql 简介 在HTML5中,大大丰富了客户端本地可以存储的内容,添加了很多功能来将原本必须保存在服务器上的数据转为保存在客户端本地,从而大大提高了Web应用程序的性能,减轻了服务器端的 ...
- curl之采集QQ空间留言
目录 主要流程解析 注意事项 扩展 完整代码示例 采集效果一览 主要流程解析 首先,打开浏览器登录QQ空间并访问留言列表 由于QQ空间的链接是https,curl方式请求https链接需要突破http ...
- Ionic Js六:切换开关操作
以下实例中,通过切换不同开关 checked 显示不同的值,true 为打开,false 为关闭. HTML 代码 <ion-header-bar class="bar-positiv ...
- 相等(==)、严格相等(===)、NaN、null、undefined、空和0
(===)如果两个引用值指向同一个对象.数组.或函数,则他们是相等的.如果指向不同的对象,则他们是不相等的,尽管两个对象具有完全一样的属性. (==)如果其中一个值是true,则将其转换为1再进行比较 ...
- python3之Django内置模板标签和过滤器
一.模板标签 内置标签: 1.autoescape 控制当前的自动转义行为,此标记采用on或者off作为参数,并确定自动转义是否在块内有效.该块以endautoescape结束标签关闭. views: ...
- 字符串hash与字典树
title: 字符串hash与字典树 date: 2018-08-01 22:05:29 tags: acm 算法 字符串 概述 这篇主要是关于字符串里的 字符串hash 和 字符串字典树,,两个都是 ...
- CLR基础
一.各个语言的长处 ①非托管C/C++可对系统进行低级控制.可完全按照自己的想法管理内存,必要时方便地创建线程②使用Microsoft Visual Basic 6.0可以快速生成UI应用程序,并可以 ...