Here is a typical IDispose implementation. What I don't understand is the destructor? If the user of your class forgets to call Dispose, wouldn't you have a resource leak since the destructor will not call r1.Dispose()?
public class DisposableObject : IDisposable
{
private bool disposed;
private UnmanagedResource r1;
public DisposableObject()
{
r1 = new UnmanagedResource();
}
~DisposableObject()
{
this.Dispose(false);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
// clean up managed resources
//call dispose on your member objects
r1.Dispose();
}
// clean up unmanaged resources
this.disposed = true;
}
}
public void SomeMethod()
{
if (this.disposed)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
}
}
6 Answers 6
No - the GC will call the destructor once all references to the object are gone (this is not deterministic, however).
Comments
If r1 is truly a native resource (which it doesn't look like it in your example), it should not be disposed of inside the if(disposing) block but after it. Pay particular attention to:
if (disposing)
{
// free managed resources
if (managedResource != null)
{
managedResource.Dispose();
managedResource = null;
}
}
// free native resources if there are any.
if (nativeResource != IntPtr.Zero)
{
Marshal.FreeHGlobal(nativeResource);
nativeResource = IntPtr.Zero;
}
From Implement IDisposable Correctly - MSDN
If r1 is a managed resource with its own implementation of IDisposable, assuming it is implemented properly, any native resources will be cleaned up properly in its finalizer (which is why you don't need to worry about it in your own).
2 Comments
Dispose(bool alsoDisposeManagedResources) instead of Dispose(bool disposing).The reason for the destructor (finalizer) to call Dispose is because Garbage Collector calls it before it collects an object, guaranteeing that at least at some point the UnmanagedResource will be freed.
By using using and try...finally you can enforce the resource to be disposed as soon as they are not needed
http://msdn.microsoft.com/en-us/library/system.object.finalize.aspx
Comments
If you really want to, you can add a finalizer:
~DisposeImplementation()
{
Dispose(false);
}
But it should only be used as a true last resort, not something to rely on directly.
Comments
In .Net, we have a feature called Garbage Collection. Garbage Collection finalizes all Objects that are not referenced (any more). Your Destructor / finalizer then calls Dispose().
If your user forgets to remove those references, you will end up with sort-of a leak.
But that's what using is for : avoid memory blockage by defining your disposables only in the scope of requirement.
Comments
The pattern exists because the garbage collector does not guarantee the order that managed objects will be garbage collected. So in the finalizer you are not guaranteed that the r1 reference is still valid.
Your r1 reference has a class name of UnmanagedResource but it is clearly a managaged type. For a real unmanned resource you would only have an IntPtr or some other token. To ensure that r1 does non like it's resource it should implement the same Dispose pattern and free it's unmanaged resource outside of the if (disposing) check.
UnmanagedResourceis wrong and misleading.r.Dispose()indicates that it is a managed resource.