Оператор Dispose в языке Fore предназначен для решения довольно узкого класса проблем, связанных с невозможностью определения момента освобождения неиспользуемых объектов. Уничтожение созданных и уже неиспользующихся объектов (на которые нет ссылок) производится сборщиком мусора (garbage collector). Запуск сборщика мусора в основном производится в моменты простоя системы. Как следствие между обнулением ссылок на объект и его фактическим уничтожением может пройти довольно большой период времени. Наличие этого периода, а также неопределенность момента его наступления, могут вызывать проблемы при разработке. Рассмотрим это на следующем классическом примере:
Sub Main;
Var
FileName: String;
Fs: FileStream;
Begin
FileName := Path.GetTempFileName;
Fs := New FileStream.Create(FileName, FileOpenMode.Create, FileShare.Exclusive);
Try
// Do something
Finally
Fs := Null;
File.Delete(FileName);
End Try;
End Sub Main;
В данном примере создается временный файл, затем с ним производятся какие-либо действия, после чего файл удаляется. При запуске примера на строке File.Delete возникнет стандартная исключительная ситуация "Процесс не может получить доступ к файлу, т.к. файл занят другим процессом". Казалось бы, что после присваивания переменной Fs значения Null единственная ссылка на объект "файловый поток" прекратит существование и файл будет закрыт. Фактически этого не происходит, так как объект "файловый поток" остается в памяти, несмотря на отсутствие ссылок, до следующей сборки мусора. Как следствие, файл не освобождается и не может быть удален.
Таким образом, мы приходим к тому, что требуется механизм своевременного освобождения ссылок на ресурсы. Для этого и предназначен оператор Dispose. Если по каким-либо причинам необходимо освободить ссылку на объект и уничтожить его, то необходимо использовать оператор Dispose с указанием переменной.
При использовании оператора есть несколько ограничений:
Данный оператор эффективно применять только к объектам системных классов, которые являются обертками над COM-объектами. Для объектов пользовательских классов, описанных прикладными разработчиками, применять его бессмысленно.
После выполнения оператора Dispose не происходит очистка ссылки на объект-обертку, переменной содержащей ссылку Null не присваивается. Производится освобождение ссылки на системный COM-объект, что позволяет ему уничтожиться и освободить занятые ресурсы. После вызова оператора Dispose любые обращения к объекту будут вызывать исключительную ситуацию.
Если на данный объект есть другие ссылки, то вызов оператора Dispose ожидаемого эффекта не даст. Для освобождения внутреннего COM-объекта необходимо разорвать все ссылки на него.
В итоге корректно работающий пример будет выглядеть таким образом:
Sub Main;
Var
FileName: String;
Fs: FileStream;
Begin
FileName := Path.GetTempFileName;
Fs := New FileStream.Create(FileName, FileOpenMode.Create, FileShare.Exclusive);
Try
// Do something
Finally
Dispose Fs;
File.Delete(FileName);
End Try;
End Sub Main;
См. также:
Операторы