Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция 2. Наследование.doc
Скачиваний:
5
Добавлен:
15.11.2019
Размер:
273.92 Кб
Скачать

Завершение ссылки на объект

Та схема управления памятью, которая была рассмотрена выше, обладает одной важной особенностью, которая имеет как положительные, так и отрицательные стороны: она работает полностью автоматически. С одной стороны, это упрощает процесс программирования. С другой — нас может не устраивать то, что процесс удаления объектов (закрытия соединения с базой данных, окна Windows и т. п.) будет происходить в соответствии с неизвестным нам алгоритмом. Например, если тип Саг устанавливает в процессе выполнения соединение с удаленным компьютером, скорее всего, мы захотим, чтобы эго соединение разрывалось в соответствии с установленными нами правилами.

Если вам нужно обеспечить возможность удаления объектов из оперативной памяти в соответствии с определенными вами правилами, первое, о чем вам необходимо позаботиться — о реализации в вашем классе метода System.Object.Finаlize( ). Заметим между прочим, что реализация этого метода по умолчанию (в базовом классе) ничего не дает. Однако, как это ни странно, в С# запрещено напрямую замещать метод System.Object.Finаlize( ). Более того, вы даже не сможете вызвать в вашем приложении этот метод напрямую! Если вы хотите, чтобы ваш пользовательский класс поддерживал метод Finalize( ), вы должны использовать в определении этого класса метод, очень похожий на деструктор C++:

// Что-то очень знакомое

public class Car : Object

{

// Деструктор С#?

~Саг( )

{

// Закрывайте все открытые объектом ресурсы!

// Далее в С# будет автоматически вызван метод Base FinalizeO

}

}

Если у вас есть опыт работы с C++, то подобный синтаксис вам покажется знакомым. В C++ деструктор класса — это специальный метод класса, имя которого выглядит как имя класса, перед которым стоит символ тильды (~). В C++ гарантируется, что этот метод будет вызван, когда ссылка на объект выходит за пределы области видимости (для типов, размещенных в стеке) или к объекту применяется оператор delete (для объектов, размещенных в области динамической памяти).

При размещении объекта С# в управляемой куче при помощи оператора new среда выполнения автоматически определяет, поддерживает ли ваш объект метод Finalize( ) (представленный в С# с помощью «деструктороподобного» синтаксиса). Если этот метод поддерживается объектом, ссылка на этот объект помечается как «завершаемая» (finalizable). При этом в специальной внутренней очереди «завершения» (finalization queue) помещается указатель на данный объект. Когда сборщик мусора приходит к выводу, что наступило время удалять данный объект из оперативной памяти, он обращается к этому указателю и запускает деструктор С#, определенный для этого класса, прежде чем будет произведено физическое удаление объекта из памяти.

Интерфейс iDisposable

Чтобы обеспечить единообразие методов, освобождающих ресурсы в разных клас-ах, библиотеки классов .NET определяют интерфейс IDisposable, который содержит единственный член — метод Dispose( ):

public interface IDisposable

{

public void Dispose();

}

С концепцией интерфейсов мы познакомимся в следующей главе. Сейчас достаточно будет отметить, что рекомендуется реализовывать этот интерфейс для всех -классов, которые должны поддерживать явную форму освобождения ресурсов. Например, применить этот интерфейс в случае класса Саг можно следующим образом:

// Реализуем IDisposable

public Car : IDisposable

{

// Это - единственный метод, который пользователь объекта должен вызвать

// вручную

public void Dispose( )

{

// ...Закрываем открытые внутренние ресурсы

}

}

Используя этот подход, мы предоставляем пользователю возможность в любой момент высвобождать наиболее ценные ресурсы, не загружая дополнительно оче-эедь завершения. Кроме того, мы вполне можем сочетать применение интерфейса .Disposable (с методом Dispose( )) и пользовательского деструктора С#.