关于.net:如何使用-C-中的-Lazy

提早初始化 是一种将对象的创立提早到第一次须要用时的技术,换句话说,对象的初始化是产生在真正须要的时候才执行,值得注意的是,术语 提早初始化提早实例化 的意思是雷同的——能够调换应用,通过应用 提早初始化 技术,能够防止应用程序不必要的计算和内存耗费,这篇文章咱们将会探讨如何在 C# 中应用 提早初始化。

有些敌人听完这些可能会懵逼,接下来用一个简略的例子来理解下 提早加载 的场景,思考上面两个类, CustomerOrder, Customer 类蕴含了一个 Orders 属性,一个人必定会有很多的订单,也就意味着它可能蕴含了很多的数据,甚至还须要连贯数据库去获取 Orders 记录,在这种场景下,没必要给 customer 汇合中的所有人都带上残缺的 orders,这个初始化开销是微小的,优化点就是不加载 Orders,直到某些 customer 真的须要 Orders 时才按需灌入。

应用 Lazy<T>

你能够本人写一段逻辑来实现 提早初始化,在 .Net Framework 4.0 之后就没必要了, 因为在 System 命名空间下曾经提供了 Lazy<T>,而且还是 线程平安 的,能够应用这个类来提早 资源密集型 的对象按需创立。

当应用 Lazy<T> 的时候,这里的 T 就是你要提早的汇合,那如何做到按需加载呢?调用 Lazy<T>.Value 即可,上面的代码片段展现了如何应用 Lazy<T>


Lazy<IEnumerable<Order>> orders = new Lazy<IEnumerable<Order>>();
IEnumerable<Order> result = lazyOrders.Value;

当初,思考上面的两个类: AuthorBlog,一个作者能够写很多文章,所以这两个类之间是 一对多 的关系,上面的代码片段展现了这种关系。


    public class Author
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Address { get; set; }
        public List<Blog> Blogs { get; set; }
    }
    public class Blog
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public DateTime PublicationDate { get; set; }
    }

值得注意的是,关系型数据库中的 一对多 关系映射到对象模型就是 Author 类中减少一个 List Blogs 属性,应用这个属性,Author 就能够维持一个或者多个 Blog 实例对象,对吧。

当初假设在 用户界面 上仅需展现 Author 的根底信息,比如说:(firstname,lastname,address),在这种场景下,给 Author 对象加载 Blogs 汇合是毫无意义的,当真的须要加载 Blogs 时,执行 Blogs.Value 即可立刻执行,上面展现了 Lazy<Blog> Blogs 的用法。


    public class Author
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Address { get; set; }
        public Lazy<IList<Blog>> Blogs => new Lazy<IList<Blog>>(() => GetBlogDetailsForAuthor(this.Id));
        private IList<Blog> GetBlogDetailsForAuthor(int Id)
        {
       //Write code here to retrieve all blog details for an author.
        }
    }

应用通用的 Lazy

接下来让咱们看看如何应用泛型的 Lazy 实现单例模式,上面的 StateManager 是线程平安的,同时为了演示 提早初始化,我应用了 动态构造函数 来确保 C# 编译器不会将它标记为 beforefieldinit


    public sealed class StateManager
    {
        private StateManager()
        {
        }

        public static StateManager Instance
        {
            get
            {
                return Nested.obj;
            }
        }
        private class Nested
        {
            static Nested()
            {
            }
            internal static readonly StateManager obj = new StateManager();
        }
    }

上面我用 Lazy<T> 来包装 StateManager,你会发现应用 Lazy<T> 来做提早初始化真的是太简略了。。。


    public class StateManager
    {
        private static readonly Lazy<StateManager> obj = new Lazy<StateManager>(() => new StateManager());
        private StateManager() { }
        public static StateManager Instance
        {
            get
            {
                return obj.Value;
            }
        }
    }

能够瞄一下下面代码的 Instance 属性,它被做成只读属性了,同时也要留神 obj.Value 也是一个只读属性。


    public class Lazy<T>
    {
        public T Value
        {
            get
            {
                if (_state != null)
                {
                    return CreateValue();
                }
                return _value;
            }
        }
    }

提早初始化 是一个很不错的性能优化技术,它容许你将那些 资源密集型 的对象提早到你真正须要加载的时候再加载,大家联合本人的场景纵情的应用吧!

译文链接:https://www.infoworld.com/art…

更多高质量干货:参见我的 GitHub: csharptranslate

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理