user2070073
user2070073

Reputation: 61

c# Dispose pattern

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);
            }

        }
    }

Upvotes: 0

Views: 2248

Answers (6)

shf301
shf301

Reputation: 31394

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.

Upvotes: 0

Sebastian Edelmeier
Sebastian Edelmeier

Reputation: 4157

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.

Upvotes: 0

Dennisch
Dennisch

Reputation: 7523

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.

Upvotes: 0

Sten Petrov
Sten Petrov

Reputation: 11040

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

Upvotes: 0

Justin Niessner
Justin Niessner

Reputation: 245389

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

Upvotes: 2

Oded
Oded

Reputation: 498904

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

Upvotes: 2

Related Questions