什么是延迟初始化,为什么它有用?

什么是对象的惰性初始化? 你怎么做,有什么优势?

延迟初始化(Lazy Initialization)是一种性能优化,您可以在实际需要之前推迟(可能是昂贵的)对象创build。

一个很好的例子就是不要在前面创build数据库连接,而只是在需要从数据库中获取数据之前。

这样做的关键原因是(通常),如果你不需要它,你可以避免完全创build对象。

正如其他人所提到的,延迟初始化是延迟初始化,直到使用组件或对象。 您可以将懒惰初始化视为YAGNI原则的运行时应用程序 – “您不会需要它”

从懒惰初始化的应用程序angular度来看,优点是用户不必为不使用的function支付初始化时间。 假设您要预先初始化应用程序的每个组件。 这可能会造成很长的开始时间 – 用户在准备使用之前必须等待几十秒或几分钟。 他们正在等待并支付可能永远不会使用或不能立即使用的function的初始化。

相反,如果您推迟初始化这些组件直到使用时间,您的应用程序将启动得更快。 当使用其他组件时,用户将仍然需要支付启动成本,但是该成本将在整个程序运行期间被分摊,而不是压缩到开始,并且用户可以将这些对象的初始化时间与它们的特征使用。

延迟初始化是延迟对象创build的概念,直到实际首次使用该对象。 如果使用得当,可以带来显着的性能提升。

就个人而言,我在.NET 2.0中创build自己的手动ORM时使用了Lazy Initialization。 从数据库加载我的集合时,集合中的实际项目被延迟初始化。 这意味着集合很快创build,但每个对象只有在我需要的时候才加载。

如果你熟悉Singleton模式,那么你也可能会看到懒惰的初始化。

public class SomeClassSingleton { private static SomeClass _instance = null; private SomeClassSingleton() { } public static SomeClass GetInstance() { if(_instance == null) _instance = new SomeClassSingleton(); return _instance; } } 

在这种情况下,SomeClass的实例不会被初始化,直到SomeClassSingleton消费者首先需要它。

在通常的计算术语中,“懒惰评估”意味着推迟对某事的处理,直到你真正需要为止。 主要的想法是,如果你不需要它,或者在你使用它之前价值会改变,你有时可以避免代价高昂的操作。

一个简单的例子是System.Exception.StackTrace。 这是一个exception的string属性,但是直到您访问它才会真正build立。 它在内部就是这样的:

 String StackTrace{ get{ if(_stackTrace==null){ _stackTrace = buildStackTrace(); } return _stackTrace; } } 

这样可以节省实际调用buildStackTrace的开销,直到有人想知道它是什么。

属性是简单地提供这种types的行为的一种方式。

对象的延迟初始化意味着它的创build被推迟到第一次使用。 (对于这个主题,术语懒惰初始化和懒惰实例是同义词。)懒惰初始化主要用于提高性能,避免浪费计算,并减less程序内存要求。 这些是最常见的情况:

当你创build一个昂贵的对象时,程序可能不会使用它。 例如,假设在内存中有一个Customer对象,该对象具有一个Orders属性,该对象包含一个Order对象的大数组,这些对象将被初始化,需要一个数据库连接。 如果用户从不要求显示订单或在计算中使用数据,则没有理由使用系统内存或计算周期来创build它。 通过使用Lazy声明Orders对象进行延迟初始化,可以避免在不使用对象时浪费系统资源。

当你创build一个昂贵的对象时,你希望推迟创build它,直到其他昂贵的操作完成。 例如,假设你的程序在启动的时候加载了几个对象实例,但是其中只有一些是立即需要的。 通过推迟不需要的对象的初始化,可以提高程序的启动性能,直到创build所需的对象。

尽pipe可以编写自己的代码来执行延迟初始化,但我们build议您使用Lazy来代替。 懒惰及其相关types也支持线程安全并提供一致的exception传播策略。

正如我迄今为止对lazy init所了解的那样,程序并没有加载/请求所有的数据。 它在从例如请求之前等待它的使用。 一个SQL服务器。

如果你有一个大表与大量子表连接的数据库,并且除非进入“编辑”或“查看详细信息”,否则懒惰初始化,你不需要从其他表中join的细节。 将有助于应用程序更快地运行,并首先根据需要“延迟加载”详细数据。

在SQL或LINQ中,您可以在数据库模型pr上设置此“设置”。 dataelement。

希望这对你的问题有意义吗?

一个webclient(例如一个浏览器)做同样的事情。 如果使用正确的话,HTML和AJAX也是一种“懒惰的初始化”,图像是“延迟加载”。

到目前为止所提到的数据库例子都不错,但并不仅限于数据访问层。 您可以将相同的原则应用于任何性能或记忆可能成为问题的情况。 一个很好的例子(虽然不是.NET)在Cocoa中,在那里你可以等待,直到用户请求一个窗口实际从nib加载它(及其关联的对象)。 这可以帮助保持内存使用率下降,并加速初始应用程序负载,特别是当您正在讨论像“首选项”窗口之类的事情时,在稍后的某个时间(如果有的话)将不再需要。

在这里您可以阅读关于使用示例代码的Lazy Initialization 。

  • 当你创build一个昂贵的对象时,程序可能不会使用它。 例如,假设在内存中有一个Customer对象,该对象具有一个Orders属性,该对象包含一个Order对象的大数组,这些对象将被初始化,需要一个数据库连接。 如果用户从不要求显示订单或在计算中使用数据,则没有理由使用系统内存或计算周期来创build它。 通过使用Lazy声明Orders对象进行延迟初始化,可以避免在不使用对象时浪费系统资源。

  • 当你创build一个昂贵的对象时,你希望推迟创build它,直到其他昂贵的操作完成。 例如,假设你的程序在启动的时候加载了几个对象实例,但是其中只有一些是立即需要的。 通过推迟不需要的对象的初始化,可以提高程序的启动性能,直到创build所需的对象。

 //Lazy instantiation delays certain tasks. //It typically improves the startup time of a C# application. using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LazyLoad { class Program { static void Main(string[] args) { Lazy<MyClass> MyLazyClass = new Lazy<MyClass>(); // create lazy class Console.WriteLine("IsValueCreated = {0}",MyLazyClass.IsValueCreated); // print value to check if initialization is over MyClass sample = MyLazyClass.Value; // real value Creation Time Console.WriteLine("Length = {0}", sample.Length); // print array length Console.WriteLine("IsValueCreated = {0}", MyLazyClass.IsValueCreated); // print value to check if initialization is over Console.ReadLine(); } } class MyClass { int[] array; public MyClass() { array = new int[10]; } public int Length { get { return this.array.Length; } } } } // out put // IsValueCreated = False // Length = 10 // IsValueCreated = True