zoukankan      html  css  js  c++  java
  • .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>实现延迟加载

  • 相关阅读:
    Entity Framework Core 2.0 新特性
    asp.net core部署时自定义监听端口,提高部署的灵活性
    asp.net core使用jexus部署在linux无法正确 获取远程ip的解决办法
    使用xshell连接服务器,数字键盘无法使用解决办法
    使用Jexus 5.8.2在Centos下部署运行Asp.net core
    【DevOps】DevOps成功的八大炫酷工具
    【Network】Calico, Flannel, Weave and Docker Overlay Network 各种网络模型之间的区别
    【Network】UDP 大包怎么发? MTU怎么设置?
    【Network】高性能 UDP 应该怎么做?
    【Network】golang 容器项目 flannel/UDP相关资料
  • 原文地址:https://www.cnblogs.com/darrenji/p/3852626.html
Copyright © 2011-2022 走看看