// кода, который выполняется при создании объекта AllTracks.
private Lazy
new Lazy
{
Console.WriteLine("Creating AllTracks object!");
return new AllTracks();
}
);
public AllTracks GetAllTracks()
{
// Возвратить все композиции.
return _allSongs.Value;
}
}
Итак, вы наверняка смогли оценить полезность класса Lazy<>. По существу этот обобщенный класс позволяет гарантировать, что затратные в плане ресурсов объекты размещаются в памяти, только когда они требуются их пользователю.
Резюме
Целью настоящей главы было прояснение процесса сборки мусора. Вы видели, что сборщик мусора запускается, только если не удается получить необходимый объем памяти из управляемой кучи (либо когда разработчик вызывает GC.Collect()). Не забывайте о том, что разработанный в Microsoft алгоритм сборки мусора хорошо оптимизирован и предусматривает использование поколений объектов, дополнительных потоков для финализации объектов и управляемой кучи для обслуживания крупных объектов.
В главе также было показано, каким образом программно взаимодействовать со сборщиком мусора с применением класса System.GC. Как отмечалось, единственным случаем, когда может возникнуть необходимость в подобном взаимодействии, является построение финализируемых или освобождаемых классов, которые имеют дело с неуправляемыми ресурсами.
Вспомните, что финализируемые типы — это классы, которые предоставляют деструктор (переопределяя метод Finalize())для очистки неуправляемых ресурсов во время сборки мусора. С другой стороны, освобождаемые объекты являются классами (или структурами не ref), реализующими интерфейс IDisposable, к которому пользователь объекта должен обращаться по завершении работы с ними. Наконец, вы изучили официальный шаблон освобождения, в котором смешаны оба подхода.
В заключение был рассмотрен обобщенный класс по имени Lazy<>. Вы узнали, что данный класс позволяет отложить создание затратных (в смысле потребления памяти) объектов до тех пор, пока вызывающая сторона действительно не затребует их. Класс Lazy<> помогает сократить количество объектов, хранящихся в управляемой куче, и также обеспечивает создание затратных объектов только тогда, когда они действительно нужны в вызывающем коде.
Часть IV
Дополнительные конструкции программирования на C#
Глава 10
Коллекции и обобщения
Любому приложению, создаваемому с помощью платформы .NET Core, потребуется решать вопросы поддержки и манипулирования набором значений данных в памяти. Значения данных могут поступать из множества местоположений, включая реляционную базу данных, локальный текстовый файл, XML-документ, вызов веб-службы, или через предоставляемый пользователем источник ввода.
В первом выпуске платформы .NET программисты часто применяли классы из пространства имен System.Collections для хранения и взаимодействия с элементами данных, используемыми внутри приложения. В версии .NET 2.0 язык программирования C# был расширен поддержкой средства под названием System.Collections.Generic.
В настоящей главе представлен обзор разнообразных пространств имен и типов коллекций (обобщенных и необобщенных), находящихся в библиотеках базовых классов .NET Core. Вы увидите, что обобщенные контейнеры часто превосходят свои необобщенные аналоги, поскольку они обычно обеспечивают лучшую безопасность в отношении типов и дают выигрыш в плане производительности. После того, как вы научитесь создавать и манипулировать обобщенными элементами внутри платформы, в оставшемся материале главы будет продемонстрировано создание собственных обобщенных методов и типов. Вы узнаете о роли where языка С#), которые позволяют строить классы, в высшей степени безопасные в отношении типов.
Побудительные причины создания классов коллекций
Несомненно, самым элементарным контейнером, который допускается применять для хранения данных приложения, считается массив. В главе 4 вы узнали, что массив C# позволяет определить набор идентично типизированных элементов (в том числе массив элементов типа System.Object, по существу представляющий собой массив данных любых типов) с фиксированным верхним пределом. Кроме того, вспомните из главы 4, что все переменные массивов C# получают много функциональных возможностей от класса System.Array. В качестве краткого напоминания взгляните на следующий код, который создает массив текстовых данных и манипулирует его содержимым разными способами: