对象的创建方式,始终代表了软件工业的生产力方向,代表了先进软件技术发展的方向,也代表了广大程序开发者的集体智慧。以new的方式创建,通过工厂方法,利用IoC容器,都以不同的方式实现了活生生实例成员的创生。而本文所关注的Lazy<T>也是干这事儿的。不过,简单说来,Lazy<T>要实现的就是按“需”创建,而不是按时创建。

我们往往有这样的情景,一个关联对象的创建需要较大的开销,为了避免在每次运行时创建这种家伙,有一种聪明的办法叫做实现“懒对象”,或者延迟加载。.NET 4.0之前,实现懒对象的机制,需要开发者自己来实现与管理,例如,你可以翻开老赵同志的较为理想的延迟代理的编写方式一文来了解其原理和场合。可喜的是,在.NET 4.0中包含的另一个好玩的家伙System.Lazy<T>。它的定义如下:

[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();
}
注:VS2010 Beta2对Lazy<T>和VS2010 Beta1有较大差异,因此本文仅以最新版本为标准,并不保证最终.NET 4.0正式版的实际情况。

假设,我们有一个大块头:

public class Big
{public int ID { get; set; }// Other resources
}

那么,可以使用如下的方式来实现Big的延迟创建:

static void Main(string[] args)
{Lazy<Big> lazyBig = new Lazy<Big>();
}

从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提供的关注度实在不少,我们眼花缭乱了。

参考文献

  • Lazy Initialization, http://msdn.microsoft.com/en-us/library/dd997286(VS.100).aspx

[你必须知道的.NET]第三十三回,深入.NET 4.0之,LazyT点滴相关推荐

  1. [你必须知道的.NET]第三十一回,深入.NET 4.0之,从“新”展望

    总体来说,这是一篇介绍性的文章,不会涉及过多技术细节和研究过程.但是,作为拉开序幕的第一页,本文以提纲挈领的方式展开对.NET 4.0的初次体验.从What's new的角度,开始我对.NET 4.0 ...

  2. [你必须知道的.NET]第三十回:.NET十年(下)

    引言 语言是程序开发者行走江湖的手上利器,各大门派的高手在论坛.博客为了自家门派争吵不已早是技术世界中的亮丽风景,虽多少为刚刚踏入江湖的新手提供了思考的素材,但也同时迷惑了初出茅庐的前行方向. 本文不 ...

  3. [你必须知道的.NET]第三十二回,,深入.NET 4.0之,Tuple一二

    anytao.net | <你必须知道的.NET>网站 | Anytao技术博客  发布日期:2009.06.01 作者:Anytao © 2009 Anytao.com ,Anytao原 ...

  4. [你必须知道的.NET]第三十五回,判断dll是debug还是release,这是个问题

    问题的提出 晚上翻着群里的聊天,发现一个有趣的问题:如何通过编码方式来判断一个dll或者exe为debug build还是release build?由于没有太多的讨论,所以我只好自己找点儿办法,试图 ...

  5. [你必须知道的.NET]第十四回:认识IL代码---从开始到现在

    本文将介绍以下内容: ·       IL代码分析方法 ·       IL命令解析 ·       .NET学习方法论 1. 引言 自从『你必须知道.NET』系列开篇以来,受到大家很多的关注和支持, ...

  6. [你必须知道的.NET]第二十八回:说说Name这回事儿

    1 缘起 老赵在谈表达式树的缓存(2):由表达式树生成字符串中提到,在描述Type信息时讨论FullName或者AssemblyQualifiedName提供完整的Type信息,虽是小话题,但却是值得 ...

  7. [你必须知道的.NET]第二十五回:认识元数据和IL(中)

    说在,开篇之前 书接上回[第二十四回:认识元数据和IL(上)],我们对PE文件.程序集.托管模块,这些概念与元数据.IL的关系进行了必要的铺垫,同时顺便熟悉了以ILDASM工具进行反编译的基本方法认知 ...

  8. [你必须知道的.NET]第二十四回:认识元数据和IL(上)

    说在,开篇之前 很早就有说说Metadata(元数据)和IL(中间语言)的想法了,一直在这篇开始才算脚踏实地的对这两个阶级兄弟投去些细关怀,虽然来得没有<第一回:恩怨情仇:is和as>那么 ...

  9. [你必须知道的.NET]第二十九回:.NET十年(上)

    引言 语言是程序开发者行走江湖的手上利器,各大门派的高手在论坛.博客为了自家门派争吵不已早是技术世界中的亮丽风景,虽多少为刚刚踏入江湖的新手提供了思考的素材,但也同时迷惑了初出茅庐的前行方向. 本文不 ...

最新文章

  1. 状态机在计算机中的应用
  2. 数据结构——线性结构
  3. Hexo+腾讯CVM+又拍云+github+gitee+coding
  4. 理解sqlalchemy与ORM
  5. mysql 慢日志报警_一则MySQL慢日志监控误报的问题分析
  6. android的应用组件,跟我学android-Android应用基本组件介绍(五)
  7. 不会装系统?有这篇就够了!
  8. [转载] python中join的使用
  9. 我能读懂的NLP技术科普书,可能也就只有它了(T ^ T)
  10. 如何阅读《深入理解计算机系统》这本书?
  11. .vb和.cs文件编译成.dll文件
  12. Layui 监听 复选框 提交表单
  13. 我是如何自学C语言的(一个菜鸟的学习路)
  14. ChatGPT突遭大面积封号!网友应急出解封教程
  15. 使用BP神经网络获得PID控制器的kp,ki,kd控制参数matlab仿真
  16. kettle数据同步从EXCL文件读取数据入库
  17. Java项目:SSH高校科研管理系统平台
  18. git 配置ssh 秘钥
  19. 自定义控件 - 流式布局(CofferFlowLayout)
  20. Facebook也要玩智能眼镜

热门文章

  1. Hadoop 配置文件 启动方式
  2. 581. Shortest Unsorted Continuous Subarray连续数组中的递增异常情况
  3. JavaScript——执行环境、变量对象、作用域链
  4. tomcat原理解析(一):一个简单的实现
  5. BIEE 目录迁移(文件夹)方式
  6. map集合遍历的五种方法
  7. 【Android 应用开发】Activity 状态保存 OnSaveInstanceState參数解析
  8. asp.net 之高速缓存
  9. pat-1136. A Delayed Palindrome (20) 模拟
  10. codeforce 884C - Bertown Subway DFS+图论