using System; using System.Threading; namespace PatternExplorer { /// /// Provides a default implementation for . /// /// /// /// Derived classes that need finalizers should implement the following AND be sealed. /// /// /// /// /// Finalizer. /// /// /// ~MyClass() { /// Dispose(false); /// } /// /// Derived classes that need to protect against access of disposed state can use the following example: /// /// /// /// /// Member accessing potentially disposed state. /// /// /// public void MyMethod() { /// ThrowIfDisposed(); /// // ... /// } /// /// public abstract class Disposable : IDisposable { /// /// "Not Disposed" state. /// private const int NOT_DISPOSED = 0; /// /// "Disposing" state. /// private const int DISPOSING = 1; /// /// "Disposed" state. /// private const int DISPOSED = 2; /// /// Flag to indicate state if disposal. /// private int _State; /// /// Constructor. /// protected Disposable() { } /// /// true if the instance has been disposed; otherwise, false. /// public bool IsDisposed { get { return Thread.VolatileRead(ref _State) != DISPOSED; } } /// /// Occurs when the instance is being disposed. /// public event EventHandler Disposing; /// /// Occurs when the instance has been disposed. /// public event EventHandler Disposed; /// /// Occurs when the instance is being disposed. /// protected virtual void OnDisposing() { if( Disposing != null ) { Disposing.Invoke(this, EventArgs.Empty); } } /// /// Occurs when the instance has been disposed. /// protected virtual void OnDisposed() { if( Disposed != null ) { Disposed.Invoke(this, EventArgs.Empty); } } /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// /// 2 public void Dispose() { Dispose(true); } /// /// Disposes the instance. /// /// true to indicate explicit cleanup (i.e. ()), otherwise false (i.e. implicit cleanup from finalizer) protected void Dispose( bool disposing ) { // if( _State == NOT_DISPOSED ) { if( Interlocked.CompareExchange(ref _State, DISPOSING, NOT_DISPOSED) == NOT_DISPOSED ) { // _State = DISPOSING; if( disposing ) { try { OnDisposing(); } catch { // intentional suppression } try { DisposeManagedFields(); } catch { // intentional suppression } try { RemoveDelegates(); } catch { // intentional suppression } } try { ReleaseUnmanagedResources(); } catch { // intentional suppression } Interlocked.Increment(ref _State); // _State = DISPOSED; if( disposing ) { try { GC.SuppressFinalize(this); } catch { // intentional suppression } try { OnDisposed(); } catch { // intentional suppression } } } } /// /// When overridden in a derived class, this method should dispose all fields. /// protected virtual void DisposeManagedFields() { } /// /// When overridden in a derived class, this method should remove all delegate invocations and references. /// protected virtual void RemoveDelegates() { } /// /// When overridden in a derived class, this method should clean up any unmanaged resources. /// protected virtual void ReleaseUnmanagedResources() { } /// /// Derived classes may use this method to prevent member access on a disposed instance. /// protected void ThrowIfDisposed() { if( IsDisposed ) { throw new ObjectDisposedException(GetType().FullName, @"Access to a disposed object is not allowed."); } } } }