Я никогда не помню всех правил для реализации интерфейса IDisposable, поэтому я попытался создать базовый класс, который позаботится обо всем этом и упростит реализацию IDisposable. Я просто хотел услышать ваше мнение, если эта реализация будет в порядке, или вы видите то, что я могу улучшить. Предполагается, что пользователь этого базового класса будет извлекать из него, а затем реализовать два абстрактных метода: ReleaseManagedResources()
и ReleaseUnmanagedResources()
. Так вот код:Правильно ли это IDisposable?
public abstract class Disposable : IDisposable
{
private bool _isDisposed;
private readonly object _disposeLock = new object();
/// <summary>
/// called by users of this class to free managed and unmanaged resources
/// </summary>
public void Dispose() {
DisposeManagedAndUnmanagedResources();
}
/// <summary>
/// finalizer is called by garbage collector to free unmanaged resources
/// </summary>
~Disposable() { //finalizer of derived class will automatically call it's base finalizer
DisposeUnmanagedResources();
}
private void DisposeManagedAndUnmanagedResources() {
lock (_disposeLock) //make thread-safe
if (!_isDisposed) { //make sure only called once
try { //suppress exceptions
ReleaseManagedResources();
ReleaseUnmanagedResources();
}
finally {
GC.SuppressFinalize(this); //remove from finalization queue since cleaup already done, so it's not necessary the garbage collector to call Finalize() anymore
_isDisposed = true;
}
}
}
private void DisposeUnmanagedResources() {
lock (_disposeLock) //make thread-safe since at least the finalizer runs in a different thread
if (!_isDisposed) { //make sure only called once
try { //suppress exceptions
ReleaseUnmanagedResources();
}
finally {
_isDisposed = true;
}
}
}
protected abstract void ReleaseManagedResources();
protected abstract void ReleaseUnmanagedResources();
}
Спасибо, Джо, да, я заберу замок в финализаторе. – 2009-05-17 15:25:09
Нет, он не может быть собран, поскольку текущий одноразовый содержит ссылку на него. –
«Нет, он не может быть собран» - это неправильно. Его можно было собрать - из MSDN: «Финализаторы двух объектов не гарантируются для запуска в каком-либо конкретном порядке, даже если один объект ссылается на другой. То есть, если объект А имеет ссылку на объект B, и оба имеют финализаторы , Объект B может быть уже завершен, когда начинается финализатор объекта A. »(см. Http://msdn.microsoft.com/en-us/library/system.object.finalize.aspx) – Joe