zoukankan      html  css  js  c++  java
  • C# Lazy<T>(转)

    .NET Framework 4 在一次次跳票中终于发布了,在一次偶然的机会,我看到了 Anytao 的 [你必须知道的.NET]第三十三回,深入.NET 4.0之,Lazy<T>点滴 。

    我没有看过在.NET Framework 4.0 beta2 的 关于 Lazy<T> 的实现,也不知道正式版与之前的版本是否有过改进(改变),我只在这里来单纯地谈在.NET Framework 4 中 Lazy<T> 的实现。

    1. Lazy<T> 概述

    我们也许会遇到这样一种情况,我们有一个大家伙(大对象)需要创建,那么这个对象的创建时需要较长的时间,同时也需要在托管堆上分配较多的空间。

    那么在.NET Framework 4 中提供了这样一个很聪明的方式:Lazy<T>(我们可以称之为懒对象)。当然,在之前,很多人也曾对其进行过自己的实现。

    那么我们在这里就可以把 Lazy<T> 的作用总结为一句话,按需延迟加载

    2. Lazy<T> 的使用

    了解了Lazy<T>的作用,让我们就来看下Lazy<T>如何应用。

    class Program
    {
    static void Main(string[] args)
    {
    Lazy<Large> lazyObject = new Lazy<Large>();
    Console.WriteLine(lazyObject.IsValueCreated);
    lazyObject.Value.Test();
    Console.WriteLine(lazyObject.IsValueCreated);
    }
    }

    [Serializable]
    class Large
    {
    public Large() { }
    public void Test()
    {
    Console.WriteLine("Test");
    }
    }

    运行结果如下:

    False

    Test

    True

    请按任意键继续 ...

    这个例子很简单,也是Lazy<T>最基本,也是最常用的应用方式。

    3. 实现自己的Lazy<T>

    在.NET Framework 4.0之前,大对象就是存在的,那么对于一个大型系统而言,怎么样对付一个大对象呢。在我看来有两点:延迟加载和即时清理。前者解决创建问题,后者解决回收问题。

    那么在来看Lazy<T>的.NET Framework实现之前,我们先来自己实现一个简单的Lazy<T>吧。

    class MyLazy<T> where T : new()
    {
    private T value;
    private bool isLoaded;
    public MyLazy()
    {
    isLoaded = false;
    }
    public T Value
    {
    get
    {
    if (!isLoaded)
    {
    value = new T();
    isLoaded = true;
    }
    return value;
    }
    }
    }

    这应该是最简单版本的Lazy<T>了,没有线程安全检测,其实什么都没有,只有着访问时创建真实对象,可是对于我们一般的应用来说也许就已经足够了。

    4. Lazy<T>的.NET Framework实现

    原本还想解释下代码的,可是太多了,解释不动了…….就写些主要把。

    其实.NET Framework和上面的实现大同小异,有两点主要的不同:

    A. 引入了Boxed内部类:

    [Serializable]
    private class Boxed
    {
    // Fields
    internal T m_value;

    // Methods
    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
    internal Boxed(T value)
    {
    this.m_value = value;
    }
    }

    该内部类取代了我在上面实现中的泛型约束,使之更通用。

    但是我们也应该注意到,如果T为结构体,那么由于T很大,所以装箱拆箱反而也许是个更耗费效率的事情,因此,个人建议,对值类型慎用Lazy<T>。

    B. 线程安全的控制

    在线程安全的控制选项中,.NET Framework为我们提供了这样的枚举选项:

    public enum LazyThreadSafetyMode
    {
    None,
    PublicationOnly,
    ExecutionAndPublication
    }

    不做多余解释,关于这三者的具体意思,MSDN中已经说的很清楚了,可参加 这里 。

    里面的代码比较麻烦,就不多说了。

    5. 完善的大对象解决方案

    在 Anytao 文章的回复中,我就提到了一点是:

    个人倒觉得Lazy+WeakReference才是实现一个大对象的完整解决之道,一个按需加载,一个不定清理..... 
    加到一起才完美。

    但是 老赵 说:

    又不是所有的大对象都需要自动清理……

    那么我就不再重复去总结了,这两句话加到一起,我想应该可以得出一个比较完善的大对象处理方案吧。

    如果这样,我们是否能对应地去创建一个单独的实现类:WeakLazy<T>呢。

    这样相当于我们有了WeakReference,有了Lazy<T>,还有了WeakLazy<T>,那么我们是不是就可以很完整地根据情况选择应用了呢!

    6. 总结

    原本想写一些稍微深入点的东西,可是写到最后,发现仍为皮毛而,叹乎…….

    转自:http://www.cnblogs.com/kym/archive/2010/02/21/1670226.html 
     

  • 相关阅读:
    Educational Codeforces Round 83 --- F. AND Segments
    Educational Codeforces Round 83 --- G. Autocompletion
    SEERC 2019 A.Max or Min
    2019-2020 ICPC Southwestern European Regional Programming Contest(Gym 102501)
    Educational Codeforces Round 78 --- F. Cards
    今天我学习了一门全新的语言
    codeforces 1323D 题解(数学)
    Educational Codeforces Round 80 (Div. 2) 题解 1288A 1288B 1288C 1288D 1288E
    Educational Codeforces Round 81 (Div. 2) 题解 1295A 1295B 1295C 1295D 1295E 1295F
    Codeforces Round #617 (Div. 3) 题解 1296C 1296D 1296E 1296F
  • 原文地址:https://www.cnblogs.com/zhangpengshou/p/2811765.html
Copyright © 2011-2022 走看看