C#基础知识回顾---你不知道的Lazy<T>
对象的创建方式,始终代表了软件工业的生产力方向,代表了先进软件技术发展的方向,也代表了广大程序开发者的集体智慧。以new的方式创建,通过工厂方法,利用IoC容器,都以不同的方式实现了活生生实例成员的创生。而本文所关注的Lazy<T>也是干这事儿的。不过,简单说来,Lazy<T>要实现的就是按“需”创建,而不是按时创建。
我们往往有这样的情景,一个关联对象的创建需要较大的开销,为了避免在每次运行时创建这种家伙,有一种聪明的办法叫做实现“懒对象”,或者延迟加载。.NET 4.0之前,实现懒对象的机制,需要开发者自己来实现与管理它的定义如下:
[Serializable]
public class Lazy<T>
{
public Lazy();
public Lazy(bool isThreadSafe);
public Lazy(Func<T> valueFactory);
public Lazy(Func<T> valueFactory, bool isThreadSafe);
public bool IsValueCreated { get; }
public T Value { get; }
public override string ToString();
}
假设,我们有一个大块头:
public class Big
{
public int ID { get; set; }
// Other resources
}
从Lazy<T>的定义可知,其Value属性就是我们包装在Lazy Wrapper中的真实Big对象,那么当我们第一次访问lazyBig.Value时,就回自动的创建Big实例。
static void Main(string[] args)
{
Lazy<Big> lazyBig = new Lazy<Big>();
Console.WriteLine(lazyBig.Value.ID);
}
当然,有其定义可知,Lazy远没有这么小儿科,它同时还可以为我们提供以下的服务:
- 通过IsValueCreated,获取是否“已经”创建了实例对象。
- 解决非默认构造函数问题。
显而易见。我们的Big类并没有提供带参数构造函数,那么如下的Big类:
public class Big
{
public Big(int id)
{
this.ID = id;
}
public int ID { get; set; }
// Other resources
}
上述创建方式将引发运行时异常,提示包装对象没有无参的构造函数。那么,这种情形下的延迟加载,该如何应对呢?其实Lazy<T>的构造中还包括:
public Lazy(Func<T> valueFactory);
它正是用来应对这样的挑战:
static void Main(string[] args)
{
// Lazy<Big> lazyBig = new Lazy<Big>();
Lazy<Big> lazyBig = new Lazy<Big>(() => new Big(100));
Console.WriteLine(lazyBig.Value.ID);
}
其实,从public Lazy(Func<T> valueFactory)的定义可知,valueFactory可以返回任意的T实例,那么任何复杂的构造函数,对象工厂或者IoC容器方式都可以在此以轻松的方式兼容,例如:
public class BigFactory
{
public static Big Build()
{
return new Big(100);
}
}
可以应用Lazy<T>和BigFactory实现Big的延迟加载:
static void Main(string[] args)
{
Lazy<Big> lazyBig = new Lazy<Big>(() => BigFactory.Build());
Console.WriteLine(lazyBig.Value.ID);
}
- 提供多线程环境支持。
另外的构造器:
public Lazy(bool isThreadSafe);
public Lazy(Func<T> valueFactory, bool isThreadSafe);
中,isThreadSafe则应用于多线程环境下,如果isThreadSafe为false,那么延迟加载对象则一次只能创建于一个线程。
关于Lazy<T>的应用,其实已经不是一个纯粹的语言问题,还涉及了对设计的考量,例如实现整个对象的延迟加载,或者实现延迟属性,考量线程安全等等。就不说教太多。因为,.NET 4.0提供的关注度实在不少,我们眼花缭乱了。
郑重声明本文非原创……
- WPF 的Main方法
- WiX制作安装包--系统必备
- 选项卡TabHost
- FPGA入门
- .NET 4 System.Threading.Barrier 类
- 终被捕!5名罗马尼亚黑客因入侵华盛顿政府摄像头被捕
- VUE 入门基础(9)
- 国家级人工智能产业基地落户松江,发布上海首款国产人工智能芯片
- C# 4.0 Optional Parameters 和Named Parameters
- 开源Web服务器GoAhead远程代码执行漏洞 影响数十万物联网设备
- MySpace:开源数据处理Qizmt
- 王劲:承受大风大浪,创业要忍人所不能忍
- 这枚三拼被榴莲卖了 众安科技收入囊中
- SQL Server数据库碎片
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- C# 的sql server like 的参数
- sql server 字符串替换函数REPLACE
- sql server 更新两个表的某个字段
- HTML 引用Css样式的四种方式
- Java也可以像python般range出连续集合
- c# dev控件 gridcontrol 数据跟随鼠标滚轮滚动也可以编辑
- Apollo(阿波罗)配置中心Java客户端使用指南使用指南
- DevExpress.LookUpEdit控件实现自动搜索定位功能 兼使用方法(looUpEdit可编辑)
- dev GridControl直接打印 纵向合并单元格
- Dooring可视化之从零实现动态表单设计器
- 我不是最后一个知道MDC的吧?
- 实战编写 wireshark 插件解析私有协议
- 安卓 APP 三代加壳方案的研究报告
- 将博客主题替换成 Clean Blog
- Go 数据存储篇(一):基于内存存储实现数据增删改查功能