Рекомендуемый шаблон IDisposable здесь . При программировании класса, который использует IDisposable, обычно вы должны использовать два шаблона:
При реализации запечатанного класса, который не использует неуправляемые ресурсы, вы просто реализуете метод Dispose, как в обычных реализациях интерфейса:
public sealed class A : IDisposable
{
public void Dispose()
{
// get rid of managed resources, call Dispose on member variables...
}
}
При реализации открытого класса сделайте это так:
public class B : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// get rid of managed resources
}
// get rid of unmanaged resources
}
// only if you use unmanaged resources directly in B
//~B()
//{
// Dispose(false);
//}
}
Обратите внимание, что я не объявил финализатор в B
; вы должны реализовывать финализатор только в том случае, если у вас есть реальные неуправляемые ресурсы, которыми можно распоряжаться. CLR имеет дело с финализуемыми объектами иначе, чем не финализируемые объекты, даже если вызывается SuppressFinalize
.
Таким образом, вы не должны объявлять финализатор, если в этом нет необходимости, но вы предоставляете наследникам вашего класса ловушку для вызова вашего Dispose
и сами реализуете финализатор, если они напрямую используют неуправляемые ресурсы:
public class C : B
{
private IntPtr m_Handle;
protected override void Dispose(bool disposing)
{
if (disposing)
{
// get rid of managed resources
}
ReleaseHandle(m_Handle);
base.Dispose(disposing);
}
~C() {
Dispose(false);
}
}
Если вы не используете неуправляемые ресурсы напрямую (SafeHandle
и друзья не учитываются, так как они объявляют свои собственные финализаторы), то не реализуйте финализатор, поскольку GC по-разному обрабатывает финализуемые классы, даже если Вы позже подавите финализатор. Также обратите внимание, что, хотя B
не имеет финализатора, он все равно вызывает SuppressFinalize
для корректной работы с любыми подклассами, которые реализуют финализатор.
Когда класс реализует интерфейс IDisposable, это означает, что где-то есть неуправляемые ресурсы, от которых нужно избавиться, когда вы закончите использовать класс. Фактические ресурсы инкапсулированы в классах; вам не нужно явно удалять их. Простой вызов Dispose()
или перенос класса в using(...) {}
обеспечит удаление любых неуправляемых ресурсов по мере необходимости.