Что такое ленивая инициализация и почему она полезна? - PullRequest
65 голосов
/ 11 июня 2009

Что такое ленивая инициализация объектов? Как вы это делаете и каковы преимущества?

Ответы [ 9 ]

86 голосов
/ 11 июня 2009

Ленивая инициализация - это оптимизация производительности, при которой вы откладываете (потенциально дорогое) создание объекта до того момента, когда оно вам действительно понадобится.

Один хороший пример - не создавать соединение с базой данных заранее, а только непосредственно перед тем, как вам нужно получить данные из базы.

Основная причина этого заключается в том, что (часто) вы можете избежать создания объекта полностью, если он вам никогда не нужен.

40 голосов
/ 11 июня 2009

Как уже упоминалось, отложенная инициализация задерживает инициализацию до тех пор, пока не будет использован компонент или объект. Вы можете просмотреть отложенную инициализацию как исполняемое приложение по принципу YAGNI - "You ain't gonna need it"

Преимущества отложенной инициализации с точки зрения приложения состоят в том, что пользователям не нужно платить время инициализации за функции, которые они не будут использовать. Предположим, вы должны были инициализировать каждый компонент вашего приложения заранее. Это может создать потенциально долгое время запуска - пользователям придется ждать десятки секунд или минут, прежде чем ваше приложение будет готово к использованию. Они ждут и платят за инициализацию функций, которые они могут никогда не использовать или не использовать сразу.

Вместо этого, если вы отложите инициализацию этих компонентов до времени использования, ваше приложение запустится намного быстрее. Пользователю все равно придется оплачивать стоимость запуска при использовании других компонентов, но эта стоимость будет амортизироваться при запуске программы, а не сокращаться в начале, и пользователь может связать время инициализации этих объектов с функциями, которыми они являются использование.

13 голосов
/ 11 июня 2009

Ленивая инициализация - это концепция отсрочки создания объекта до тех пор, пока объект не будет фактически впервые использован. При правильном использовании это может привести к значительному увеличению производительности.

Лично я использовал Lazy Initialization при создании собственного ORM, вручную свернутого в .NET 2.0. При загрузке моих коллекций из базы данных фактические элементы в коллекции были лениво инициализированы. Это означало, что коллекции создавались быстро, но каждый объект загружался только тогда, когда мне это нужно.

Если вы знакомы с шаблоном 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.

5 голосов
/ 11 июня 2009

В общих вычислительных терминах «ленивая оценка» означает откладывать обработку чего-либо до тех пор, пока она вам действительно не понадобится. Основная идея заключается в том, что иногда вы можете избежать дорогостоящих операций, если вам это не нужно, или если значение изменится до того, как вы его используете.

Простым примером этого является System.Exception.StackTrace. Это строковое свойство для исключения, но оно фактически не создается, пока вы не получите к нему доступ. Внутренне это делает что-то вроде:

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

Это избавляет вас от необходимости фактического вызова buildStackTrace, пока кто-нибудь не захочет увидеть, что это такое.

Свойства являются одним из способов просто обеспечить такой тип поведения.

2 голосов
/ 05 января 2014
//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
2 голосов
/ 24 мая 2011

Ленивая инициализация объекта означает, что его создание откладывается до его первого использования. (В этом разделе термины «отложенная инициализация» и «отложенная реализация» являются синонимами.) «Ленивая инициализация» в основном используется для повышения производительности, предотвращения расточительных вычислений и снижения требований к памяти программ. Это наиболее распространенные сценарии:

Если у вас есть дорогостоящий объект, и программа может его не использовать. Например, предположим, что у вас в памяти есть объект Customer, у которого есть свойство Orders, которое содержит большой массив объектов Order, для инициализации которого требуется соединение с базой данных. Если пользователь никогда не просит отобразить ордера или использовать данные в вычислениях, то нет причин использовать системную память или вычислительные циклы для его создания. Используя Lazy для объявления объекта Orders для отложенной инициализации, вы можете избежать потери системных ресурсов, когда объект не используется.

Если у вас есть дорогостоящий объект, и вы хотите отложить его создание до завершения других дорогостоящих операций. Например, предположим, что ваша программа загружает несколько экземпляров объекта при запуске, но только некоторые из них требуются немедленно. Вы можете улучшить производительность запуска программы, отложив инициализацию ненужных объектов до тех пор, пока необходимые объекты не будут созданы.

Хотя вы можете написать свой собственный код для выполнения отложенной инициализации, мы рекомендуем использовать вместо него Lazy. Lazy и связанные с ним типы также поддерживают безопасность потоков и обеспечивают согласованную политику распространения исключений.

2 голосов
/ 05 ноября 2010

Здесь вы можете прочитать о Ленивая инициализация с примером кода.

  • Когда у вас есть объект, который дорого создавать и программу может не использовать его. Например, предположим, что у вас в памяти клиент объект, который имеет свойство Orders который содержит большой массив порядка объекты, которые должны быть инициализированы, требует подключения к базе данных. Если пользователь никогда не просит отображать ордера или использовать данные в вычислении, затем нет причин использовать систему память или вычислительные циклы для создания Это. Используя Lazy, чтобы объявить Объекты заказов для ленивых инициализация, вы можете избежать тратить системные ресурсы, когда объект не используется.

  • Когда у вас есть объект, который дорого создавать, а ты хочешь отложить его создание до другого дорогие операции были завершено. Например, предположим, что ваша программа загружает несколько объектов случаи, когда это начинается, но только некоторые из них требуются немедленно. Вы можете улучшить стартап выполнение программы отсрочка инициализации объекты, которые не требуются до необходимые объекты были создано.

1 голос
/ 11 июня 2009

Примеры баз данных, которые были упомянуты до сих пор, хороши, но они не ограничиваются только уровнем доступа к данным. Вы можете применить те же принципы к любой ситуации, когда производительность или память могут быть проблемой. Хороший пример (хотя и не .NET) в Какао, где вы можете подождать, пока пользователь не запросит окно, чтобы фактически загрузить его (и связанные с ним объекты) из пера. Это может помочь уменьшить использование памяти и ускорить первоначальную загрузку приложения, особенно когда вы говорите о таких вещах, как окна настроек, которые не понадобятся до некоторого времени, если вообще когда-либо.

1 голос
/ 11 июня 2009

Насколько я понял о ленивом init, так это то, что программа не загружает / не запрашивает все данные за один раз. Он ожидает его использования, прежде чем запросить его, например, от. SQL-сервер.

Если у вас есть база данных с большой таблицей, объединенной с большим количеством подтаблиц, и вам не требуются сведения, объединенные из других таблиц, кроме случаев «редактирования» или «просмотра сведений», тогда Lazy Init. поможет приложению работать быстрее и сначала "лениво загрузить" данные по мере необходимости.

В SQL или LINQ вы можете установить эту «настройку» в вашей модели базы данных pr. dataelement.

Надеюсь, это имеет какой-то смысл для вашего вопроса?

Веб-клиент (например, браузер) делает то же самое. Изображения «загружаются лениво» после HTML, а AJAX также является «своего рода ленивым инициатором», если используется правильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...