Язык программирования C#9 и платформа .NET5
private void CleanUp(bool disposing){// Удостовериться, не выполнялось ли уже освобождениеif (!this.disposed){// Если disposing равно true, тогда// освободить все управляемые ресурсы.if (disposing){// Освободить управляемые ресурсы.}// Очистить неуправляемые ресурсы.}disposed = true;}~MyResourceWrapper(){// Вызвать вспомогательный метод.// Указание false означает, что// очистку запустил сборщик мусора.CleanUp(false);}}Обратите внимание, что в
теперь определен закрытый вспомогательный метод по имениMyResourceWrapper. Передавая ему true в качестве аргумента, мы указываем, что очистку инициировал пользователь объекта, поэтому должны быть очищены все управляемые и неуправляемые ресурсы. Однако когда очистка инициируется сборщиком мусора, при вызове методуCleanup()передается значениеCleanup(), чтобы внутренние освобождаемые объекты не освобождались (поскольку нельзя рассчитывать на то, что они все еще присутствуют в памяти). И, наконец, перед выходом изfalseпеременная-членCleanup()типаdisposedустанавливается вbool, что дает возможность вызывать методtrueмного раз без возникновения ошибки.Dispose()На заметку! После того как объект был "освобожден", клиент по-прежнему может обращаться к его членам, т.к. объект пока еще находится в памяти. Следовательно, в надежном классе оболочки для ресурсов каждый член также необходимо снабдить дополнительной логикой, которая бы сообщала: "если объект освобожден, то ничего не делать, а просто возвратить управление".
Чтобы протестировать финальную версию класса
, модифицируйте свой файлMyResourceWrapper, как показано ниже:Program.csusing System;using FinalizableDisposableClass;Console.WriteLine("***** Dispose() / Destructor Combo Platter *****");// Вызвать метод Dispose() вручную, что не приводит к вызову финализатора.MyResourceWrapper rw = new MyResourceWrapper();rw.Dispose();// He вызывать метод Dispose(). Это запустит финализатор,// когда объект будет обрабатываться сборщиком мусора.MyResourceWrapper rw2 = new MyResourceWrapper();В коде явно вызывается метод
на объекте rw, поэтому вызов деструктора подавляется. Тем не менее, мы "забыли" вызвать метод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 композиций.