0

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);
 }
 }
 }
P.Brian.Mackey
44.4k71 gold badges249 silver badges360 bronze badges
asked Feb 13, 2013 at 21:55
1
  • Your name for UnmanagedResource is wrong and misleading. r.Dispose() indicates that it is a managed resource. Commented Feb 13, 2013 at 22:43

6 Answers 6

2

No - the GC will call the destructor once all references to the object are gone (this is not deterministic, however).

answered Feb 13, 2013 at 21:59
Sign up to request clarification or add additional context in comments.

Comments

2

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).

answered Feb 13, 2013 at 22:01

2 Comments

+1. Yes - the distinction is managed resources will be non-deterministically freed by run-time around the time destructor is called (or even if one does not exist), but non-managed resources must be released in destructor (which is done by Dispose(false) ).
Side note: it would have been easier to understand if MSDN use signature Dispose(bool alsoDisposeManagedResources) instead of Dispose(bool disposing).
0

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

answered Feb 13, 2013 at 22:01

Comments

0

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.

answered Feb 13, 2013 at 22:02

Comments

0

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.

answered Feb 13, 2013 at 22:04

Comments

0

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.

answered Feb 13, 2013 at 22:04

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.