Является ли IDisposable.Dispose() автоматически вызванным?
Возможный дубликат:
Будет ли вызов сборщика мусора IDisposable.Dispose для меня?
У меня есть класс, у которого есть неуправляемые ресурсы. Мой класс реализует интерфейс IDisposable
и освобождает неуправляемые ресурсы в методе Dispose()
. Должен ли я вызвать метод Dispose()
или он будет автоматически вызван каким-то образом? Позвонит ли это сборщик мусора?
Ответы
Ответ 1
Dispose()
не будет вызываться автоматически. Если есть финализатор, он будет вызываться автоматически. Реализация IDisposable
позволяет пользователям своего класса рано выпускать ресурсы, а не ждать сборщика мусора.
Предпочтительным способом для клиента является использование оператора using
, который обрабатывает автоматический вызов Dispose()
, даже если есть исключения.
Правильная реализация IDisposable
такова:
class MyClass : IDisposable
{
private bool disposed = false;
void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if(!disposed)
{
if(disposing)
{
// Manual release of managed resources.
}
// Release unmanaged resources.
disposed = true;
}
}
~MyClass() { Dispose(false); }
}
Если пользователь класса вызывает Dispose()
, очистка происходит непосредственно. Если объект улавливается сборщиком мусора, он вызывает Dispose(false)
для очистки. Обратите внимание, что при вызове из финализатора (метод ~MyClass
) управляемые ссылки могут быть недопустимыми, поэтому можно освободить только неуправляемые ресурсы.
Ответ 2
Чтобы убедиться, что ресурсы правильно расположены, вам необходимо реализовать IDisposable
и вызвать Dispose
в деструкторе (финализатор).
class Foo : IDisposable
{
private bool m_disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~Foo()
{
Dispose(false);
}
protected void Dispose(bool disposing)
{
if (!m_disposed)
{
if (disposing)
{
//release managed resources
}
//release unmanaged resources
m_disposed = true;
}
}
}
Ответ 3
Если вы создаете экземпляр объекта в инструкции using
, Dispose() вызывается для вас, когда код выходит из блока using
using(var myObject = new MyDisposableObject())
{
blah();
} // Dispose() is called here (or whenever the code exits the block)
Если вы не используете using
, то вам (код вызова) удалять свой объект, явно вызывая Dispose().
Кроме того, вы (разработчик MyObject) можете добавить поддержку финализатора в случае, если ваш вызывающий абонент не вызывает Dispose(). Подробнее здесь.
Ответ 4
Вам нужно будет вызвать этот метод вручную, возможно, в конструкции типа
using(var myclass = new MyClass())
{
// do something with myclass
}
// now 'myclass'is Disposed