对象的创建方式,始终代表了软件工业的生产力方向,代表了先进软件技术发展的方向,也代表了广大程序开发者的集体智慧。以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提供的关注度实在不少,我们眼花缭乱了。

郑重声明本文非原创……

最新文章

  1. 用jquery实现遮罩层
  2. 获取表单选中的值(利用php和js两种方式)
  3. Redis 的Lua Script脚本功能
  4. HDU 2393 Higher Math
  5. Goldeneye.py网站压力测试工具2.1版源码
  6. 尝试使用Memcached
  7. Vue.js + Seajs 实例(包含vue-router使用)
  8. Rails关闭html_safe字符串过滤
  9. linux中epoll模型
  10. php留言板程序
  11. Jquery的动态切换图片
  12. 剑指Offer-从上往下打印二叉树
  13. Java链接DB2的4种基本类型【转】
  14. sed语法2
  15. 【java】模板方法设计模式
  16. MySQL 5.6 GTID Replication
  17. java 基础one ---运算符and流程控制
  18. JSON数据的优化
  19. nodejs 热更新插件
  20. [Command] alias - 别名

热门文章

  1. linux下git远程仓库的搭建
  2. Maven的阿里云镜像
  3. android.os.NetworkOnMainThreadException的解决方案
  4. C++ OCCI API数据库操作之连接、返回查询结果集为json格式
  5. sql解决避免除以零的错误
  6. JQuery Mobile - html5+CSS 禁止IOS长按复制粘贴实现
  7. 【算法python实现】 -- 不同路径
  8. [学习笔记]状压dp
  9. Atom 清空残余数据
  10. Vue过渡动画—Vue学习笔记