惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
酷 壳 – CoolShell
酷 壳 – CoolShell
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
腾讯CDC
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Jina AI
Jina AI
N
Netflix TechBlog - Medium
有赞技术团队
有赞技术团队
博客园 - 【当耐特】
MongoDB | Blog
MongoDB | Blog
P
Proofpoint News Feed
L
LangChain Blog
aimingoo的专栏
aimingoo的专栏
GbyAI
GbyAI
B
Blog
F
Fortinet All Blogs
T
Tailwind CSS Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
Google Developers Blog
A
About on SuperTechFans
C
Check Point Blog
Microsoft Security Blog
Microsoft Security Blog
MyScale Blog
MyScale Blog
B
Blog RSS Feed

博客园 - Anytao

[视频],花一分钟来看看Worktile是如何为团队协作而生的 如何使用Worktile进行敏捷项目开发管理 有一个团队协同工具,叫Worktile 上博客园,用工作台 [WP7], #01, Windows Phone 7培训点滴 [推荐], 开始Azure之旅,参加深度培训 [推荐],与创业公司一起成长 [开发故事],第十五回,在Js中应用命名空间 [推荐], 游戏?地图?还是交友?尽在16fun 2010,因为不同:挺进2010,记忆2009 [你必须知道的.NET]第三十五回,判断dll是debug还是release,这是个问题 [关注]日益火爆的Social media - Anytao - 博客园 [开发故事]第五回,用想要的域名运行你的本地Web应用 [你必须知道的.NET]第三十四回,object成员,不见了! [活动]博文视点Open Party上海站职业生涯分论坛 哥写的不是代码,是寂寞 [一些思考]转身,关注更高。 [书评杂谈]观止,观而不止 [书评杂谈]《我也能做CTO》 书评
[你必须知道的.NET]第三十三回,深入.NET 4.0之,Lazy<T&g...
Anytao · 2009-10-29 · via 博客园 - Anytao

anytao.net | 《你必须知道的.NET》网站 | Anytao技术博客 

发布日期:2009.10.29 作者:Anytao
© 2009 Anytao.com ,Anytao原创作品,转贴请注明作者和出处。

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

参考文献

更多闲言碎语,关注anytao.net