如何使用 C# 中的 Lazy

一线码农上海 2021/1/23 8:08:25

延迟初始化 是一种将对象的创建延迟到第一次需要用时的技术,换句话说,对象的初始化是发生在真正需要的时候才执行,值得注意的是,术语 延迟初始化 和 延迟实例化 的意思是相同的——可以互换使用,通过使用 延迟初始化 技术,可以避免应用程序不必要的计算和内存消耗,…

延迟初始化 是一种将对象的创建延迟到第一次需要用时的技术,换句话说,对象的初始化是发生在真正需要的时候才执行,值得注意的是,术语 延迟初始化延迟实例化 的意思是相同的——可以互换使用,通过使用 延迟初始化 技术,可以避免应用程序不必要的计算和内存消耗,这篇文章我们将会讨论如何在 C# 中使用 延迟初始化。

有些朋友听完这些可能会懵逼,接下来用一个简单的例子来了解下 延迟加载 的场景,考虑下面两个类, CustomerOrder, Customer 类包含了一个 Orders 属性,一个人肯定会有很多的订单,也就意味着它可能包含了很多的数据,甚至还需要连接数据库去获取 Orders 记录,在这种场景下,没必要给 customer 集合中的所有人都带上完整的 orders,这个初始化开销是巨大的,优化点就是不加载 Orders,直到某些 customer 真的需要 Orders 时才按需灌入。

使用 Lazy

你可以自己写一段逻辑来实现 延迟初始化,在 .Net Framework 4.0 之后就没必要了, 因为在 System 命名空间下已经提供了 Lazy,而且还是 线程安全 的,可以使用这个类来延迟 资源密集型 的对象按需创建。

当使用 Lazy 的时候,这里的 T 就是你要延迟的集合,那如何做到按需加载呢?调用 Lazy.Value 即可,下面的代码片段展示了如何使用 Lazy

Lazy> orders = new Lazy>();
IEnumerable 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 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 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> Blogs => new Lazy>(() => GetBlogDetailsForAuthor(this.Id));
        private IList 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 来包装 StateManager,你会发现使用 Lazy 来做延迟初始化真的是太简单了。。。

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

可以瞄一下上面代码的 Instance 属性,它被做成只读属性了,同时也要注意 obj.Value 也是一个只读属性。

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

延迟初始化 是一个很不错的性能优化技术,它允许你将那些 资源密集型 的对象延迟到你真正需要加载的时候再加载,大家结合自己的场景尽情的使用吧!

更多高质量干货:参见我的 GitHub: [csharptranslate] github.com/ctripxchuang/csharptranslate

随时随地学软件编程-关注百度小程序和微信小程序
关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。
本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。
[如何使用 C# 中的 Lazy]http://www.zyiz.net/tech/detail-151231.html

上一篇:如何在 ASP.NET Core 5 中重载 Action 方法

下一篇:如何使用 C# 中的 FileSystemWatcher

赞(0)

共有 条评论 网友评论

验证码: 看不清楚?
    关注微信小程序
    程序员编程王-随时随地学编程

    扫描二维码或查找【程序员编程王】

    可以随时随地学编程啦!

    技术文章导航 更多>
    扫一扫关注最新编程教程