Построение освобождаемых объектов
Как вы уже видели, финализаторы могут использоваться для освобождения неуправляемых ресурсов при запуске сборщика мусора. Тем не менее, учитывая тот факт, что многие неуправляемые объекты являются "ценными элементами" (вроде низкоуровневых дескрипторов для файлов или подключений к базам данных), зачастую полезно их освобождать как можно раньше, не дожидаясь наступления сборки мусора. В качестве альтернативы переопределению метода Finalize
IDisposable, в котором определен единственный метод по имени Dispose:public interface IDisposable
{
void Dispose;
}
При реализации интерфейса IDisposable
Dispose перед тем, как позволить объектной ссылке покинуть область действия. Таким способом объект может производить любую необходимую очистку неуправляемых ресурсов без помещения в очередь финализации и ожидания, пока сборщик мусора запустит логику финализации класса.На заметку!
ИнтерфейсIDisposable может быть реализован структурами не ref и классами (в отличие от переопределения метода Finalize, что допускается только для классов), т.к. метод Dispose вызывается пользователем объекта, а не сборщиком мусора. Освобождаемые структуры ref обсуждались в главе 4.В целях иллюстрации применения интерфейса IDisposable
SimpleDispose. Ниже приведен модифицированный класс MyResourceWrapper, который вместо переопределения метода System.Object.Finalize теперь реализует интерфейс IDisposable:using System;
namespace SimpleDispose
{
// Реализация интерфейса IDisposable.
class MyResourceWrapper : IDisposable
{
// После окончания работы с объектом пользователь
. // объекта должен вызывать этот метод
public void Dispose
{
// Очистить неуправляемые ресурсы...
. // Освободить другие освобождаемые объекты, содержащиеся внутри.
// Только для целей тестирования
Console.WriteLine("***** In Dispose! *****");
}
}
}
Обратите внимание, что метод Dispose
Dispose для любых других освобождаемых объектов, которые содержатся внутри типа. В отличие от Finalize в методе Dispose вполне безопасно взаимодействовать с другими управляемыми объектами. Причина проста: сборщик мусора не имеет понятия об интерфейсе IDisposable, а потому никогда не будет вызывать метод Dispose. Следовательно, когда пользователь объекта вызывает данный метод, объект все еще существует в управляемой куче и имеет доступ ко всем остальным находящимся там объектам. Логика вызова метода Dispose прямолинейна:using System;
using System.IO;
using SimpleDispose;
Console.WriteLine("***** Fun with Dispose *****\n");
// Создать освобождаемый объект и вызвать метод Dispose
.// для освобождения любых внутренних ресурсов
MyResourceWrapper rw = new MyResourceWrapper;
rw.Dispose;
Console.ReadLine;
Конечно, перед попыткой вызова метода Dispose
IDisposable. Хотя всегда можно выяснить, какие типы в библиотеках базовых классов реализуют IDisposable, заглянув в документацию, программная проверка производится с помощью ключевого слова is или as (см. главу 6):Console.WriteLine("***** Fun with Dispose *****\n");
MyResourceWrapper rw = new MyResourceWrapper;
if (rw is IDisposable)
{
rw.Dispose;
}
Console.ReadLine;
Приведенный пример раскрывает очередное правило, касающееся управления памятью.
Бьёрн Страуструп , Ирина Сергеевна Козлова , Бьерн Страуструп , Валерий Федорович Альмухаметов
Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT