Что такое ленивая инициализация объектов? Как вы это делаете и каковы преимущества?
83
Ленивая инициализация - это оптимизация производительности, при которой вы откладываете (потенциально дорогое) создание объекта до того момента, когда он вам действительно понадобится.
Один хороший пример - не создавать соединение с базой данных заранее, а только непосредственно перед тем, как вам нужно будет получить данные из базы данных.
Основная причина этого заключается в том, что (часто) вы можете полностью избежать создания объекта, если он вам никогда не понадобится.
Lazy
опубликован в следующем вопросе SO: stackoverflow.com/a/15894928/4404962 это предложение решило именно то, что нам нужно было решить - используяLazy
в качестве ключевого принципалаКак уже упоминалось, ленивая инициализация откладывает инициализацию до тех пор, пока не будет использован компонент или объект. Вы можете рассматривать ленивую инициализацию как приложение времени выполнения по принципу YAGNI - "
You ain't gonna need it
"Преимущества отложенной инициализации с точки зрения приложения состоят в том, что пользователям не нужно тратить время на инициализацию для функций, которые они не будут использовать. Предположим, вы должны инициализировать каждый компонент своего приложения заранее. Это может создать потенциально долгое время запуска - пользователям придется ждать десятки секунд или минут, прежде чем ваше приложение будет готово к использованию. Они ждут и платят за инициализацию функций, которые могут никогда не использовать или не использовать сразу.
Вместо этого, если вы отложите инициализацию этих компонентов до времени использования, ваше приложение запустится намного быстрее. При использовании других компонентов пользователю все равно придется оплачивать начальную стоимость, но эта стоимость будет амортизироваться на протяжении всего выполнения программы, а не конденсироваться в начале, и пользователь может связать время инициализации этих объектов с функциями, которыми они являются. с помощью.
источник
Ленивая инициализация - это концепция откладывания создания объекта до момента, когда он действительно впервые будет использован. При правильном использовании это может привести к значительному увеличению производительности.
Лично я использовал отложенную инициализацию при создании собственной 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.
источник
В общих компьютерных терминах «ленивая оценка» означает откладывание обработки чего-либо до тех пор, пока оно вам действительно не понадобится. Основная идея состоит в том, что иногда можно избежать дорогостоящих операций, если он окажется вам не нужен или если значение изменится до того, как вы его используете.
Простым примером этого является System.Exception.StackTrace. Это строковое свойство исключения, но на самом деле оно не создается, пока вы не получите к нему доступ. Внутри он делает что-то вроде:
String StackTrace{ get{ if(_stackTrace==null){ _stackTrace = buildStackTrace(); } return _stackTrace; } }
Это избавит вас от накладных расходов на вызов buildStackTrace до тех пор, пока кто-то не захочет узнать, что это такое.
Свойства - это один из способов просто обеспечить такое поведение.
источник
Здесь вы можете прочитать о ленивой инициализации с примером кода.
источник
Ленивая инициализация объекта означает, что его создание откладывается до первого использования. (В этом разделе термины «ленивая инициализация» и «ленивое создание экземпляров» являются синонимами.) Ленивая инициализация в основном используется для повышения производительности, предотвращения бесполезных вычислений и уменьшения требований к памяти программы. Это наиболее распространенные сценарии:
Когда у вас есть объект, который дорого создавать, и программа может его не использовать. Например, предположим, что у вас есть в памяти объект Customer, у которого есть свойство Orders, содержащее большой массив объектов Order, для инициализации которых требуется соединение с базой данных. Если пользователь никогда не просит отображать Заказы или использовать данные в вычислениях, то нет причин использовать системную память или вычислительные циклы для их создания. Используя Lazy для объявления объекта Orders для отложенной инициализации, вы можете избежать траты системных ресурсов, когда объект не используется.
Когда у вас есть объект, создание которого требует больших затрат, и вы хотите отложить его создание до завершения других дорогостоящих операций. Например, предположим, что ваша программа загружает несколько экземпляров объекта при запуске, но только некоторые из них требуются немедленно. Вы можете улучшить скорость запуска программы, отложив инициализацию ненужных объектов до тех пор, пока не будут созданы необходимые объекты.
Хотя вы можете написать свой собственный код для выполнения отложенной инициализации, мы рекомендуем вместо этого использовать Lazy. Lazy и связанные с ним типы также поддерживают потокобезопасность и обеспечивают согласованную политику распространения исключений.
источник
//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
источник
Что я понял о ленивой инициализации, так это то, что программа не загружает / не запрашивает все данные за один раз. Он ожидает его использования, прежде чем запрашивать его, например. SQL-сервер.
Если у вас есть база данных с большой таблицей, объединенной с большим количеством подтаблиц, и вам не требуются детали, соединенные с другими таблицами, если вы не входите в «редактировать» или «просматривать детали», тогда Lazy Init. поможет приложению работать быстрее и сначала «лениво» загружать данные при необходимости.
В SQL или LINQ вы можете установить этот «параметр» в вашей модели базы данных pr. dataelement.
Надеюсь, в этом есть смысл для вашего вопроса?
Веб-клиент (например, браузер) делает то же самое. Изображения "лениво загружаются" после HTML, и AJAX также является "разновидностью ленивой инициализации", если используется правильно.
источник
Примеры баз данных, которые были упомянуты до сих пор, хороши, но они не ограничиваются только уровнем доступа к данным. Вы можете применить те же принципы к любой ситуации, когда производительность или память могут быть проблемой. Хороший пример (хотя и не .NET) - в Какао, где вы можете подождать, пока пользователь не запросит окно, чтобы фактически загрузить его (и связанные с ним объекты) из пера. Это может помочь снизить использование памяти и ускорить начальную загрузку приложения, особенно когда вы говорите о таких вещах, как окна настроек, которые не понадобятся до некоторого времени, если вообще когда-либо.
источник