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