Skip to content

Instantly share code, notes, and snippets.

@timdetering
Last active May 1, 2017 16:59
Show Gist options
  • Save timdetering/b99bc162443d95ed6f9e5e62e03bbefc to your computer and use it in GitHub Desktop.
Save timdetering/b99bc162443d95ed6f9e5e62e03bbefc to your computer and use it in GitHub Desktop.
IDisposable, Done Right
using System;
namespace DisposableExample
{
//-------------------------------------------------------------------
/// <summary>
/// Provides the base implementation for the <see cref="T:System.IDisposable"/> interface.
/// </summary>
/// <seealso cref="https://gist.github.com/timdetering/b99bc162443d95ed6f9e5e62e03bbefc"/>
/// <seealso cref="https://gist.github.com/thinktainer/5633464"/>
/// <seealso cref="https://lostechies.com/chrispatterson/2012/11/29/idisposable-done-right/"/>
/// <seealso cref="https://www.codeproject.com/Articles/15360/Implementing-IDisposable-and-the-Dispose-Pattern-P"/>
/// <seealso cref="https://gist.github.com/YTsalko/3959764239beb59051f83c6a132c022f"/>
/// <seealso cref="https://gist.github.com/fallenidol/5c990b56454b053b0f31b6b497d76ba9"/>
//-------------------------------------------------------------------
public class DisposableClass : IDisposable
{
public DisposableClass()
{
//
// When an object’s constructor throws an exception, the runtime considers the object to have never
// existed. And while the GC will release any object allocated by the constructor, it will not call the
// Dispose method on any disposable objects.
// Therefore it is the responsiblity of the object creating references to managed objects in the
// constructor (or even more importantly, unmanaged objects that consume limited system resources, such
// as file handles, socket handles, or threads). It should ensure to dispose of those resources in the
// case of a constructor exception by using a try/catch block.
//
}
//-------------------------------------------------------------------
/// <summary>
/// Releases unmanaged resources and performs other cleanup operations before the object is reclaimed by garbage collection.
/// Allows this object to attempt to free resources and perform other cleanup operations before it is reclaimed by garbage collection.
/// </summary>
//-------------------------------------------------------------------
~DisposableClass()
{
this.Dispose(false);
}
//-------------------------------------------------------------------
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// Releases all resources used by the object.
/// </summary>
//-------------------------------------------------------------------
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
//-------------------------------------------------------------------
/// <summary>
/// Releases the unmanaged resources used by the component and optionally releases the managed resources.
/// </summary>
/// <param name="disposeManaged">
/// <b>true</b> if managed resources should be disposed; otherwise, <b>false</b>.
/// </param>
/// <remarks>
/// This method is called by the public <see cref="Dispose"/> method and the Finalize method. Dispose invokes the protected Dispose(Boolean) method with the <i>disposeManaged</i> parameter set to true. Finalize invokes Dispose(Boolean) with <i>disposeManaged</i> set to false.
/// </remarks>
/// <seealso href="http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx"/>
//-------------------------------------------------------------------
protected virtual void Dispose(bool disposeManaged)
{
if (false == _isDisposed)
{
try
{
if (true == disposeManaged)
{
// free other managed objects that implement
// IDisposable only
}
// release any unmanaged objects
// set the object references to null
}
finally
{
_isDisposed = true;
}
}
}
//-------------------------------------------------------------------
/// <summary>
/// Validate the object instance has not been disposed.
/// </summary>
//-------------------------------------------------------------------
protected void ValidateNotDisposed()
{
if (true == _isDisposed)
{
throw new ObjectDisposedException(this.GetType().Name);
}
}
private bool _isDisposed;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment