zoukankan      html  css  js  c++  java
  • 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提供的关注度实在不少,我们眼花缭乱了。

     郑重声明本文非原创……

     

  • 相关阅读:
    Eclipse 导入项目乱码问题(中文乱码)
    sql中视图视图的作用
    Java基础-super关键字与this关键字
    Android LayoutInflater.inflate(int resource, ViewGroup root, boolean attachToRoot)的参数理解
    Android View和ViewGroup
    工厂方法模式(java 设计模式)
    设计模式(java) 单例模式 单例类
    eclipse乱码解决方法
    No resource found that matches the given name 'Theme.AppCompat.Light 的完美解决方案
    【转】使用 Eclipse 调试 Java 程序的 10 个技巧
  • 原文地址:https://www.cnblogs.com/smiler/p/3264968.html
Copyright © 2011-2022 走看看