Sunday, July 4, 2010

C# tip - 7/3/2010 (2)

This tip goes along with the previous tip for today:  implement Dispose pattern with those object that need resource cleanup.


  1. Root base class implements IDisposable interface
    • Add a finalizer as a defensive mechanism (this will keep resources longer in memory if Dispose is not called but will dispose of resources in time)
    • Both Dispose and finalizer should be virtual methods for derived classes to override
  2. Derived class must have a finalizer as a defensive mechanism (this will keep resources longer in memory if Dispose is not called but will dispose of resources in time)
  3. Implement IDisposable, which requires you to implement Dispose method, which does the following:
    1. frees unmanaged resources
    2. frees all managed resources
    3. sets flag indicating that the object has been disposed
    4. suppress finalization
    5. call base class to clean up all of its resources
      • this can be done by implementing virtual Dispose(bool) method that allows factoring out common tasks between Dispose and finalize and call the base classes
    6. only release resources in Dispose and finalize methods.  Do not do anything else in those methods since you may unintentionally "revive" the object again, preventing it from being garbage collected.
    class Base : IDisposable
    {
        private bool _alreadyDisposed = false;


        ~Base()
        {
            Dispose(false);
        }


        public int Age { get; set; }


        #region IDisposable Members


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


        protected virtual void Dispose(bool isDisposing)
        {
            if (_alreadyDisposed)
                return;
            if (isDisposing)
            {
                //free managed resources
            }
            //free unmanaged resources
            _alreadyDisposed = true;
        }


        #endregion
    }



    class Derived :Base
    {
        private bool _disposed = false;
        public int Time { get; set; }
        public void PrintStuff()
        {
            Console.WriteLine(this.GetType());
        }




        ~Derived()
        {
            Dispose(false);
        }

        protected virtual void Dispose(bool isDisposing)
        {
            if (_disposed)
                return;
            if (isDisposing)
            {
                //free managed resources
            }
            //free unmanaged resources
            //call base class here
            base.Dispose(isDisposing);
            _disposed = true;
        }


    }

No comments:

Labels