Правило.
Неплохо вызывать методDispose на любом создаваемом напрямую объекте, если он поддерживает интерфейс IDisposable. Предположение заключается в том, что когда проектировщик типа решил реализовать метод Dispose, тогда тип должен выполнять какую-то очистку. Если вы забудете вызвать Dispose, то память в конечном итоге будет очищена (так что можно не переживать), но это может занять больше времени, чем необходимо.С предыдущим правилом связано одно предостережение. Несколько типов в библиотеках базовых классов, которые реализуют интерфейс IDisposable
Dispose в попытке сделать имя метода очистки более естественным для определяющего его типа. В качестве примера можно взять класс System.IO.FileStream, который реализует интерфейс IDisposable (и потому поддерживает метод Dispose), но также определяет следующий метод Close, предназначенный для той же цели:// Предполагается, что было импортировано пространство имен System.IO
static void DisposeFileStream
{
FileStream fs = new FileStream("myFile.txt", FileMode.OpenOrCreate);
// Мягко выражаясь, сбивает с толку!
// Вызовы этих методов делают одно и то же!
fs.Close;
fs.Dispose;
}
В то время как "закрытие" (close) файла выглядит более естественным, чем его "освобождение" (dispose), подобное дублирование методов очистки может запутывать. При работе с типами, предлагающими псевдонимы, просто помните о том, что если тип реализует интерфейс IDisposable
Dispose всегда является безопасным способом действия.Повторное использование ключевого слова using в C#
Имея дело с управляемым объектом, который реализует интерфейс IDisposable
Dispose типа будет вызываться даже в случае генерации исключения во время выполнения:Console.WriteLine("***** Fun with Dispose *****\n");
MyResourceWrapper rw = new MyResourceWrapper ;
try
{
// Использовать члены rw.
}
finally
{
// Всегда вызывать Dispose, возникла ошибка или нет.
rw.Dispose;
}
Хотя это является хорошим примером защитного программирования, в действительности лишь немногих разработчиков привлекает перспектива помещения каждого освобождаемого типа внутрь блока try/finally
Dispose. Того же самого результата можно достичь гораздо менее навязчивым способом, используя специальный фрагмент синтаксиса С#, который выглядит следующим образом:Console.WriteLine("***** Fun with Dispose *****\n");
// Метод Dispose вызывается автоматически
// при выходе за пределы области действия using.
using(MyResourceWrapper rw = new MyResourceWrapper)
{
// Использовать объект rw.
}
Если вы просмотрите код CIL операторов верхнего уровня посредством ildasm.exe
using на самом деле расширяется до логики try/finally с вполне ожидаемым вызовом Dispose:.method private hidebysig static void
'
{
...
.try
{
} // end .try
finally
{
IL_0019: callvirt instance void [System.Runtime]System.IDisposable::Dispose
} // end handler
} // end of method '
На заметку!
Попытка примененияusing к объекту, который не реализует интерфейс IDisposable, приводит к ошибке на этапе компиляции.Несмотря на то что такой синтаксис устраняет необходимость вручную помещать освобождаемые объекты внутрь блоков try/finally
using в C# имеет двойной смысл (импортирование пространств имен и вызов метода Dispose). Однако при работе с типами, которые поддерживают интерфейс IDisposable, такая синтаксическая конструкция будет гарантировать, что используемый объект автоматический вызовет свой метод Dispose по завершении блока using.Бьёрн Страуструп , Ирина Сергеевна Козлова , Бьерн Страуструп , Валерий Федорович Альмухаметов
Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT