Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Руководство_по_C#.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
10.01 Mб
Скачать

13.5Финализируемые объекты

В самом главном базовом классе .NET — System.Object — имеется виртуальный метод по имени Finalize(). В предлагаемой по умолчанию реализации он ничего особенного не делает:

// Класс System.Object

public class Object

{

protected virtual void Finalize () {}

}

За счет его переопределения в специальных классах устанавливается специфическое место для выполнения любой необходимой данному типу логики по очистке. Из-за того, что метод Finalize() по определению является защищенным (protected), вызывать его напрямую из класса экземпляра с помощью операции точки не допускается. Вместо этого метод Finalize() (если он поддерживается) будет автоматически вызываться сборщиком мусора перед удалением соответствующего объекта из памяти.

Переопределять метод Finalize() в типах структур нельзя. Это вполне логичное ограничение, поскольку структуры представляют собой типы значения, которые изначально никогда не размещаются в управляемой памяти и, следовательно, никогда не подвергаются процессу сборки мусора. Однако в случае создания структуры, которая содержит ресурсы, нуждающиеся в очистке, вместо этого метода можно реализовать интерфейс IDisposable.

Разумеется, вызов метода Finalize() будет происходить (в конечном итоге) либо во время естественной активизации процесса сборки мусора, либо во время его принудительной активизации программным образом с помощью GC.Collect(). Помимо этого, финализатор типа будет автоматически вызываться и при выгрузке из памяти домена, который отвечает за обслуживание приложения. Некоторым по опыту работы с .NET уже может быть известно, что домены приложений (AppDomain) применяются для обслуживания исполняемой сборки и любых необходимых внешних библиотек кода. Пока что необходимо обратить внимание лишь на то, что при выгрузке домена приложения из памяти CLR-среда будет автоматически вызывать финализаторы для каждого финализируемого объекта, который был создан во время существования AppDomain.

Что бы не подсказывали инстинкты разработчика, в подавляющем большинстве классов C# необходимость в создании явной логики по очистке или специального финализатора возникать не будет. Объясняется это очень просто: если в классах используются лишь другие управляемые объекты, все они рано или поздно все равно будут подвергаться сборке мусора. Единственным случаем, когда может возникать потребность в создании класса, способного выполнять после себя процедуру очистки, является работа с неуправляемыми ресурсами (такими как низкоуровневые файловые дескрипторы, низкоуровневые неуправляемые соединения с базами данных, фрагменты неуправляемой памяти и т.п.).

Внутри .NET неуправляемые ресурсы появляются в результате непосредственного вызова API-интерфейса операционной системы с помощью служб PInvoke (Platform Invocation Services — службы вызова платформы) или применения очень сложных сценариев взаимодействия с СОМ. Ознакомьтесь со следующим правилом сборки мусора:

Единственная причина переопределения Finalize() связана с использованием в классе C# каких-то неуправляемых ресурсов через PInvoke или сложных процедур взаимодействия с СОМ (обычно посредством членов типа System.Runtime.InteropServices.Marshal).