.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 ...
随机推荐
- R vs Python:构建data.frame、读取csv与统计描述
一.Python 数据框就是典型的关系型数据库的数据存储形式,每一行是一条记录,每一列是一个属性,最终构成表格的形式,这是数据科学家必须熟悉的最典型的数据结构. 1.构建数据框 import pand ...
- Struts 2 - Architecture
From a high level, Struts2 is a pull-MVC (or MVC2) framework. The Model-View-Controller pattern in S ...
- **后台怎么处理JSON数据中含有双引号?
http://bbs.csdn.net/topics/390578406?page=1 注意是后台,不是用js另外我这个json是直接取得别人的传过来的字符串,不是我自己拼写的,所以我自己不能做到转义 ...
- 《精通Python设计模式》学习之抽象工厂
这种工厂模式用得少, 可能在游戏类的编程中用得比较多吧. 这个思路清晰一定要OK的. class Frog: def __init__(self, name): self.name = name de ...
- 非ROOT用户不能识别声卡问题
将非ROOT用户加入到audio组中即可 sudo usermod -a -G audio usrname
- 【BZOJ】1016: [JSOI2008]最小生成树计数
题解 考虑kruskal 我们都是从边权最小的边开始取,然后连在一起 那我们选出边权最小的一堆边,然后这个图就分成了很多联通块,把每个联通块内部用矩阵树定理算一下生成树个数,再把联通块缩成一个大点,重 ...
- WCF服务发布到IIS中去(VS2013+win7系统)
第一个WCF程序 1. 新建立空白解决方案,并在解决方案中新建项目,项目类型为:WCF服务应用程序.建立完成后如下图所示: 2.删除系统生成的两个文件IService1.cs与Service1.svc ...
- 使用 Python 可以做什么?
翻译自 <Python学习手册(第5版)> Systems Programming Python 对操作系统服务的内置接口使其非常适合编写可移植.可维护的系统管理工具和实用程序 utili ...
- 图形文件元数据管理工具exiv2
图形文件元数据管理工具exiv2 图形文件通常都包含多种元数据,如Exif.IPTC.XMP.这些信息往往是渗透人员收集的目标.为了便于管理这些信息,Kali Linux内置了专用工具exiv2. ...
- OpenContrail 体系
OpenContrail 体系架构文档 1 概述1.1 使用案例1.2 OpenContrail控制器和vRouter1.3 虚拟网络1.4 Overlay Networking1.5 ...