Отложенная инициализация и тип Lazy
Приложение может использовать множество классов и объектов. Однако есть вероятность, что не все создаваемые объекты будут использованы. Особенно это касается больших приложений. Например:
class Reader
{
Library library = new Library();
public void ReadBook()
{
library.GetBook();
Console.WriteLine("Читаем бумажную книгу");
}
public void ReadEbook()
{
Console.WriteLine("Читаем книгу на компьютере");
}
}
class Library
{
private string[] books = new string[99];
public void GetBook()
{
Console.WriteLine("Выдаем книгу читателю");
}
}
Есть класс Library, представляющий библиотеку и хранящий некоторый набор книг в виде массива. Есть класс читателя Reader, который хранит ссылку на объект библиотеки, в которой он записан. У читателя определено два метода: для чтения электронной книги и для чтения обычной книги. Для чтения обычной книги необходимо обратиться к методу класса Library, чтобы получить эту книгу.
Но что если читателю вообще не придется читать обычную книгу, а только электронные, например, в следующем случае:
Reader reader = new Reader();
reader.ReadEbook();
В этом случае объект library в классе читателя никак не будет использоваться и будет только занимать место памяти. Хотя надобности в нем не будет.
Для подобных случаев в .NET определен специальный класс Lazy<T>. Изменим класс читателя следующим образом:
class Reader
{
Lazy<Library> library = new Lazy<Library>();
public void ReadBook()
{
library.Value.GetBook();
Console.WriteLine("Читаем бумажную книгу");
}
public void ReadEbook()
{
Console.WriteLine("Читаем книгу на компьютере");
}
}
Класс Library остается прежнем. Но теперь класс читателя содержит ссылку на библиотеку в виде объекта Lazy<Library>. А чтобы обратиться к самой библиотеке и ее методам, надо использовать выражение library.Value - это и есть объект Library.
Что меняет в поведении класса Reader эта замена? Рассмотрим его применение:
Reader reader = new Reader();
reader.ReadEbook();
reader.ReadBook();
Непосредственно объект Library задействуется здесь только на третьей строке в методе reader.ReadBook(), который вызывает в свою очередь метод library.Value.GetBook(). Поэтому вплоть до третьей строки объект Library, используемый читателем, не будет создан. Если мы не будем применять в программе метод reader.ReadBook(), то объект библиотеки тогда вобще не будет создан, и мы избежим лишних затрат памяти. Таким образом, Lazy<T> гарантирует нам, что объект будет создан только тогда, когда в нем есть необходимость.