什么是对象的延迟初始化?你是怎么做到的,有什么好处?
答案 0 :(得分:86)
延迟初始化是一种性能优化,您可以在实际需要之前推迟(可能是昂贵的)对象创建。
一个很好的例子是不预先创建数据库连接,但只是在您需要从数据库获取数据之前。
这样做的关键原因是(通常)如果你从不需要它,你可以避免完全创建对象。
答案 1 :(得分:40)
正如其他人所提到的,延迟初始化会延迟初始化,直到使用组件或对象。您可以将延迟初始化视为 YAGNI原则的运行时应用程序 - “You ain't gonna need it
”
从延迟初始化的应用程序角度来看,用户不必为不使用的功能支付初始化时间。假设您要预先初始化应用程序的每个组件。这可能会创建一个可能很长的启动时间 - 用户必须等待几十秒或几分钟才能准备好应用程序。他们正在等待并支付他们可能永远不会使用或不立即使用的功能的初始化。
相反,如果您推迟初始化这些组件直到使用时间,您的应用程序将更快启动。在使用其他组件时,用户仍然需要支付启动成本,但是该成本将在程序运行期间摊销,而不是压缩到开头,用户可以将这些对象的初始化时间与它们的功能相关联。使用
答案 2 :(得分:13)
延迟初始化是在实际首次使用对象之前推迟对象创建的概念。如果使用得当,可以显着提高性能。
就个人而言,我在.NET 2.0中创建自己的手动ORM时使用了Lazy Initialization。从数据库加载我的集合时,集合中的实际项目是惰性初始化的。这意味着集合是快速创建的,但每个对象只在我需要时加载。
如果你熟悉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使用者首次需要之前不会初始化。
答案 3 :(得分:5)
在一般的计算术语中,“懒惰评估”意味着将处理推迟到实际需要之前。主要的想法是,如果您不需要昂贵的操作,或者在使用之前价值会发生变化,您有时可以避免代价高昂的操作。
一个简单的例子是System.Exception.StackTrace。这是异常的字符串属性,但在访问它之前它实际上并未构建。在内部它做了类似的事情:
String StackTrace{
get{
if(_stackTrace==null){
_stackTrace = buildStackTrace();
}
return _stackTrace;
}
}
这可以节省实际调用buildStackTrace的开销,直到有人想要查看它是什么。
属性是简单地提供此类行为的一种方法。
答案 4 :(得分:2)
在这里,您可以阅读带有示例代码的Lazy Initialization。
当你有一个对象时 创建昂贵,程序 可能不会使用它。例如,假设 你在记忆中拥有一个顾客 具有Orders属性的对象 包含大量Order 要初始化的对象 需要数据库连接。如果 用户永远不会要求显示订单 或者在计算中使用数据 没有理由使用系统 要创建的内存或计算周期 它。通过使用Lazy来声明 懒惰的Orders对象 初始化,你可以避免浪费 对象所在的系统资源 没用过。
当你有一个对象时 创造昂贵,你想要 将其创作推迟到其他之后 昂贵的业务已经 完成。例如,假设 你的程序加载了几个对象 它开始时的实例,但仅限于 其中一些是立即需要的。 您可以改善启动 该计划的表现 推迟初始化 直到需要的对象 所需的对象已经 创建
答案 5 :(得分:2)
对象的延迟初始化意味着它的创建将延迟到首次使用。 (对于本主题,术语延迟初始化和延迟实例化是同义词。)延迟初始化主要用于提高性能,避免浪费计算,并减少程序内存需求。这些是最常见的情况:
当你有一个昂贵的对象创建时,程序可能不会使用它。例如,假设您在内存中有一个Customer对象,该对象具有Orders属性,该属性包含要初始化的大量Order对象,需要数据库连接。如果用户从未要求显示订单或在计算中使用数据,则没有理由使用系统内存或计算周期来创建订单。通过使用Lazy声明Orders对象进行延迟初始化,可以避免在不使用对象时浪费系统资源。
如果您有一个创建成本高昂的对象,并且您希望将其创建推迟到其他昂贵的操作完成之后。例如,假设您的程序在启动时加载了多个对象实例,但是只需要立即执行其中一些对象实例。您可以通过在创建所需对象之前推迟不需要的对象的初始化来提高程序的启动性能。
虽然您可以编写自己的代码来执行延迟初始化,但我们建议您使用Lazy。 Lazy及其相关类型也支持线程安全并提供一致的异常传播策略。
答案 6 :(得分:2)
//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
答案 7 :(得分:1)
到目前为止,我对lazy init的理解是程序不会加载/请求所有数据一次。在从例如请求它之前等待它的使用。一个SQL服务器。
如果你有一个大表与大量子表连接的数据库,你不需要从其他表中加入细节,除非进入“编辑”或“查看详细信息”,然后是Lazy Init。将帮助应用程序更快地进行,并根据需要首先“延迟加载”详细数据。
在SQL或LINQ中,您可以在数据库模型pr上设置此“设置”。 dataelement。
希望这对你的问题有意义吗?
webclient(例如浏览器)做同样的事情。如果正确使用HTML和AJAX也是一种“懒惰的初始化”,那么这些图像是“延迟加载的”。
答案 8 :(得分:1)
到目前为止已经提到的数据库示例很好,但它不仅限于数据访问层。您可以将相同的原则应用于可能需要考虑性能或内存的任何情况。一个很好的例子(尽管不是.NET)在Cocoa中,你可以等到用户请求窗口从笔尖实际加载它(及其相关对象)。这可以帮助减少内存使用量并加快初始应用程序负载,尤其是当您谈论的是像以前那样不需要的“首选项”窗口之类的东西,如果有的话。