Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю
private void CleanUp(bool disposing)
{
// Удостовериться, не выполнялось ли уже освобождение
if (!this.disposed)
{
// Если disposing равно true, тогда
// освободить все управляемые ресурсы.
if (disposing)
{
// Освободить управляемые ресурсы.
}
// Очистить неуправляемые ресурсы.
}
disposed = true;
}
~MyResourceWrapper()
{
// Вызвать вспомогательный метод.
// Указание false означает, что
// очистку запустил сборщик мусора.
CleanUp(false);
}
}
Обратите внимание, что в
MyResourceWrapper
Cleanup()
Cleanup()
false
Cleanup()
disposed
bool
true
Dispose()
На заметку! После того как объект был "освобожден", клиент по-прежнему может обращаться к его членам, т.к. объект пока еще находится в памяти. Следовательно, в надежном классе оболочки для ресурсов каждый член также необходимо снабдить дополнительной логикой, которая бы сообщала: "если объект освобожден, то ничего не делать, а просто возвратить управление".
Чтобы протестировать финальную версию класса
MyResourceWrapper
Program.cs
using System;
using FinalizableDisposableClass;
Console.WriteLine("***** Dispose() / Destructor Combo Platter *****");
// Вызвать метод Dispose() вручную, что не приводит к вызову финализатора.
MyResourceWrapper rw = new MyResourceWrapper();
rw.Dispose();
// He вызывать метод Dispose(). Это запустит финализатор,
// когда объект будет обрабатываться сборщиком мусора.
MyResourceWrapper rw2 = new MyResourceWrapper();
В коде явно вызывается метод
Dispose()
Dispose()
rw2
На этом исследование особенностей управления объектами со стороны исполняющей среды через сборку мусора завершено. Хотя дополнительные (довольно экзотические) детали, касающиеся процесса сборки мусора (такие как слабые ссылки и восстановление объектов), здесь не рассматривались, полученных сведений должно быть вполне достаточно, чтобы продолжить изучение самостоятельно. В завершение главы мы взглянем на программное средство под названием ленивое (отложенное) создание объектов.
Ленивое создание объектов
При создании классов иногда приходится учитывать, что отдельная переменная-член на самом деле может никогда не понадобиться из-за того, что пользователь объекта не будет обращаться к методу (или свойству), в котором она используется. Действительно, подобное происходит нередко. Однако проблема может возникнуть, если создание такой переменной-члена сопряжено с выделением большого объема памяти.
В качестве примера предположим, что строится класс, который инкапсулирует операции цифрового музыкального проигрывателя. В дополнение к ожидаемым методам вроде
Play()
Pause()
Stop()
Song
AllTracks
Создайте новый проект консольного приложения по имени
LazyObjectInstantiation
<b>// Song.cs</b>
<b>namespace LazyObjectInstantiation</b>
<b>{</b>
<b> // Представляет одиночную композицию.</b>
class Song
{
public string Artist { get; set; }
public string TrackName { get; set; }
public double TrackLength { get; set; }
}
}
<b>// AllTracks.cs</b>
<b>using System;</b>
<b>namespace LazyObjectInstantiation</b>
<b>{</b>
<b> // Представляет все композиции в проигрывателе.</b>
class AllTracks
{
// Наш проигрыватель может содержать
// максимум 10 000 композиций.