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 withusing
keyword.using
is callingIDisposable
.Dispose method in the background- This method should be public then
protected Dispose(bool)
method is meant to be called from finalizer via GCSuppressFinalize
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 callDispose
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 onDispose(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