• .NET泛型04,使用Lazy<T>实现延迟加载


    对于一些"大对象"的创建,我们常常希望延迟加载,即在需要的时候再创建对象实例。现在Lazy<T>很好地支持了这一特点。主要包括:

      没有Lazy<T>之前

    在没有Lazy<T>之前,我们通过如下方式实现延迟加载。

    public class LazySinleton
    {
        private LazySingleton()
        {}
     
        public static LazySingleton Instance
        {
            get
            {
                return Lazy.data;
            }
        }
     
        private class Lazy
        {
            static Lazy()
            {}
     
            internal static readonly LazySingleton data = new LazySingleton();
        }
    }
     

    以上
    ● 通过私有构造函数屏蔽了LazySingleton类通过构造函数创建的方式
    ● 私有嵌套类Lazy的data字段负责提供一个LazySingleton的实例
    ● 只能通过LazySingleton的属性Instance,才能拿到内部类Lazy.data所代表的实例

      Lazy<T>实例

    先看Lazy<T>的定义:

    public class Lazy<T>
    {
        public Lazy();
        public Lazy(bool isThreadSafe);
        public Lazy(Func<T> valueFactory);
        public Lazy(LazyThreadSafeMode mode);
        public Lazy(Func<T> valueFactory, bool isThreadSafe);
        public Lazy(Funct<T> valueFactory, LazyThreadSafetyMode mode);
    
        public bool IsValueCreated{get;}
        public T Value {get;}
        public override string ToStirng();
    }

    通过Lazy<T>的构造函数重载创建对象,再通过体现延迟加载的Value属性来实现对象的创建,并获取对象实例。

    public class SomeClass
    {
        public int ID{get;set;}
    }
    
    Lazy<SomeClass> temp = new Lazy<SomeClass>();
    Console.WriteLine(temp.Value.ID);

    以上,只适用于没有构造函数的情况,如果有构造函数如何处理呢?
    --使用public Lazy(Func<T> valueFactory),通过委托创建对象

    pubic class SomeClass
    {
        public int ID{get;set;}
        public SomeClass(int id)
        {
            this.ID = id;
        }
    }
    
    Lazy<SomeClass> temp = new Lazy<SomeClass>(() => new Big(100));
    Console.WriteLine(temp.Value.ID);

      延迟加载的本质

    创建自定义延迟加载类。

    public class MyLazy<T>
        {
            private volatile object boxed; //volatile说明在多线程状况下,也可以修改该字段
            private Func<T> valueFactory; //委托,用来生产T对象实例
    
            static MyLazy(){}
            public MyLazy(){}
    
            public MyLazy(Func<T> valueFactory)
            {
                this.valueFactory = valueFactory;
            }
    
            public T Value
            {
                get
                {
                    Boxed boxed = null;
                    if (this.boxed != null)
                    {
                        boxed = this.boxed as Boxed;
                        if (boxed != null)
                        {
                            return boxed.value;
                        }
                    }
                    return this.Init();
                }
            }
    
            //初始化对象实例
            private T Init()
            {
                Boxed boxed = null;
                if (this.boxed == null)
                {
                    boxed = this.CreateValue();
                    this.boxed = boxed;
                }
                return boxed.value;
            }
    
            //创建内部类实例
            private Boxed CreateValue()
            {
                //如果创建对象实例的委托valueFactory存在
                if (this.valueFactory != null)
                {
                    //就通过委托生成对象实例
                    return new Boxed(this.valueFactory());
                }
                else
                {
                    //否则,通过反射生成对象实例
                    return new Boxed((T)Activator.CreateInstance(typeof(T)));
                }
            }
    
            //内部嵌套类,通过构造函数对其字段赋值
            private class Boxed
            {
                internal T value;
                internal Boxed(T value)
                {
                    this.value = value;
                }
            }
        }

    自定义带构造函数的类。

    public class Big
        {
            public int ID { get; set; }
            public Big(int id)
            {
                this.ID = id;
            }
        }

    自定义创建对象实例的工厂类。

    public class BigFactory
        {
            public static Big Build()
            {
                return new Big(10);
            }
        }


    客户端调用。

    class Program
        {
            static void Main(string[] args)
            {
                MyLazy<Big> temp = new MyLazy<Big>(() => BigFactory.Build());
                Console.WriteLine(temp.Value.ID);
                Console.ReadKey();
            }
        }

    延迟加载的本质大致是:

    ● 由延迟加载类的内部嵌套类产生对象实例
    ● 再通过延迟加载类的某个属性来延迟获取对象实例,而对象实例是通过委托等方式创建的

    参考资料:
    《你必须知道的.NET(第2版)》,作者王涛。

    ".NET泛型"系列包括:

    .NET泛型01,为什么需要泛型,泛型基本语法

    .NET泛型02,泛型的使用

    .NET泛型03,泛型类型的转换,协变和逆变

    .NET泛型04,使用Lazy<T>实现延迟加载

  • 相关阅读:
    servlet 传值和取值问题
    .net 获取存储过程返回值和Output输出参数值
    游标使用
    java中直接根据Date获取明天的日期
    Linux通配符与特殊符号知识大全
    zabbix监控
    KVM介绍 虚拟化简史
    GFS文件系统
    Oracle JOB定时器
    IDEA JSP 不能使用EL表达式
  • 原文地址:https://www.cnblogs.com/darrenji/p/3852626.html
Copyright © 2020-2023  润新知