IDisposable interface pattern

Example implementation of IDisposable

public class MyResource : IDisposable
{
    public MyResource(IntPtr handle)
    {
        this.handle = handle;
    }

    public void Dispose()
    {
        Dispose(disposing: true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if(!this.disposed)
        {
            if(disposing)
            {
                component.Dispose();
            }
           
            CloseHandle(handle);
            handle = IntPtr.Zero;
            disposed = true;
        }
    }

    ~MyResource()
    {
        Dispose(disposing: false);
    }
}

MyResource object have pointer which is unmanaged. This is why this class should implement IDisposable interface. Implementation should be correct according to recommended pattern (see below for documentation).

There a re few points to highlight here:

  • IDisposable is meant to be used with using keyword.
  • using is calling IDisposable.Dispose method in the background
  • This method should be public then
  • protected Dispose(bool) method is meant to be called from finalizer via GC
  • SuppressFinalize disables this object from finalization mechanism in GC to prevent finalization code to be executed second time (see here)
  • Finalization is called from GC *only* if whoever is using this object will forget to use using or otherwise fail to call Dispose manually
  • Dispose must be save to call multiple times (if(!this.disposed))
  • Dispose(true) is meant to dispose also any other managed resources this implementation relies on
  • Dispose(false) is meant to be called from GC finalization mechanism. All managed resource are most likely already disposed so we cannot dispose them again

Further read:

https://learn.microsoft.com/en-us/dotnet/api/system.idisposable?view=net-6.0

Leave a Reply

Your email address will not be published. Required fields are marked *

Solve : *
10 + 4 =