Sunday, October 10, 2010

C#.net - IDisposable Interface

What is Grabage Collection?
Garbage collection is a CLR (Common Language Runtime) feature,which automatically manage memory.CLR automatically release objects when they are no longer in ues and refernced.CLR runs on non-deterministic to see the unused objects and cleans them.

What is IDisposable Interface?
IDisposable is an interface defined in the System namespace. The interface defines a single method, named "Dispose", that is used to perform clean-up activities for an object when it is no longer required. The method may be called manually, when an object's work is finished, or automatically during garbage collection.

The IDisposable interface was designed to provide a standard way to release unmanaged resources. These are resources that the garbage collector does not manage on our behalf and is unable to clean up automatically. They include items such as streams, files, database connections and handles. If the memory and system resources that they use are not properly released, your software may suffer from memory leaks or problems due to locked resources.

Let see how to implement IDisposable Interface.

Step 1
Create a console application.

Step 2
Add a new class name DisposeDemo and implement IDisposable Interface,it is look like this



 public class DisposeDemo : IDisposable
    {
        #region Declaration

        private Boolean IsDisposed = false;
        private Stream StreamObj = null;

        #endregion

        #region Dispose Method
        /// <summary>
        /// All managed and unmanaged resources can be released
        /// 
        /// If disposing equals true, the method has been called directly
        /// or indirectly by a user's code. Managed and unmanaged resources
        /// can be disposed.

        /// If disposing equals false, the method has been called by the
        /// runtime from inside the finalizer and you should not reference
        /// other objects. Only unmanaged resources can be disposed.

        /// </summary>
        /// <param name="Disposing"></param>
        private void Dispose(Boolean Disposing)
        {
            try
            {
                if (this.IsDisposed == false)
                {
                    if (Disposing == true)
                    {
                        StreamObj.Dispose();  
                    }
                    StreamObj = null; 
                }
                this.IsDisposed = true;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        #endregion

        #region IDisposable Member

        /// <summary>
        /// Used to clean up and free unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            try
            {
                Dispose(true);

                // Request that the system not call the finalizer for specified object.
                System.GC.SuppressFinalize(this);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        #endregion

        #region Property
        /// <summary>
        /// When the object is disposed then it will throw ObjectDisposedException
        /// it is an optional property.
        /// </summary>
        private  Boolean IsDispose
        {
            get
            {
                Boolean Flag = false;
                try
                {
                    if (IsDisposed == true)
                    {
                        Flag = true;
                        throw new ObjectDisposedException(this.GetType().FullName);
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
                return Flag;
            }
        }
       
       
        #endregion

        #region Print Data
        /// <summary>
        /// It will first check the object is disposed or not if object is not dispose then it will print data otherwise it will throw exception.
        /// </summary>
        public void PrintData()
        {
            try
            {
                if (!IsDispose)
                {
                   StreamObj=System.IO.File.OpenRead(AppDomain.CurrentDomain.BaseDirectory+"\\TextFile.txt");
                   System.Console.WriteLine("File Length\t:\t"+StreamObj.Length.ToString());        
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        #endregion

        #region Destructor

        /// <summary>
        /// This destructor will run only if the Dispose method
        /// does not get called.
        /// It gives your base class the opportunity to finalize.
        /// Do not provide destructors in types derived from this class.
        /// </summary>
        ~DisposeDemo()
        {
            // Do not re-create Dispose clean-up code here.
            // Calling Dispose(false) is optimal in terms of
            // readability and maintainability.

            Dispose(false);   
        }

        #endregion
    }

Step 3
Add the following code in program class.Note that the eight line of code causes an exception as we are trying to access a member after the object was disposed.it is look like this

static void Main(string[] args)
        {
            try
            {
                DisposeDemo DD = new DisposeDemo(); // create a instance of class
                
                DD.PrintData(); // print the data
 
                DD.Dispose(); // Dispose the object

                DD.PrintData(); // throw ObjectDisposedException
  
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex.Message);     
            }
        }

Full Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;



namespace ConIDisposable
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                DisposeDemo DD = new DisposeDemo(); // create a instance of class
                
                DD.PrintData(); // print the data
 
                DD.Dispose(); // Dispose the object

                DD.PrintData(); // throw ObjectDisposedException
  
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex.Message);     
            }
        }
    }

    public class DisposeDemo : IDisposable
    {
        #region Declaration

        private Boolean IsDisposed = false;
        private Stream StreamObj = null;

        #endregion

        #region Dispose Method
        /// <summary>
        /// All managed and unmanaged resources can be released
        /// 
        /// If disposing equals true, the method has been called directly
        /// or indirectly by a user's code. Managed and unmanaged resources
        /// can be disposed.

        /// If disposing equals false, the method has been called by the
        /// runtime from inside the finalizer and you should not reference
        /// other objects. Only unmanaged resources can be disposed.

        /// </summary>
        /// <param name="Disposing"></param>
        private void Dispose(Boolean Disposing)
        {
            try
            {
                if (this.IsDisposed == false)
                {
                    if (Disposing == true)
                    {
                        StreamObj.Dispose();  
                    }
                    StreamObj = null; 
                }
                this.IsDisposed = true;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        #endregion

        #region IDisposable Member

        /// <summary>
        /// Used to clean up and free unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            try
            {
                Dispose(true);

                // Request that the system not call the finalizer for specified object.
                System.GC.SuppressFinalize(this);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        #endregion

        #region Property
        /// <summary>
        /// When the object is disposed then it will throw ObjectDisposedException
        /// it is an optional property.
        /// </summary>
        private  Boolean IsDispose
        {
            get
            {
                Boolean Flag = false;
                try
                {
                    if (IsDisposed == true)
                    {
                        Flag = true;
                        throw new ObjectDisposedException(this.GetType().FullName);
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
                return Flag;
            }
        }
       
       
        #endregion

        #region Print Data
        /// <summary>
        /// It will first check the object is disposed or not if object is not dispose then it will print data otherwise it will throw exception.
        /// </summary>
        public void PrintData()
        {
            try
            {
                if (!IsDispose)
                {
                   StreamObj=System.IO.File.OpenRead(AppDomain.CurrentDomain.BaseDirectory+"\\TextFile.txt");
                   System.Console.WriteLine("File Length\t:\t"+StreamObj.Length.ToString());        
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        #endregion

        #region Destructor

        /// <summary>
        /// This destructor will run only if the Dispose method
        /// does not get called.
        /// It gives your base class the opportunity to finalize.
        /// Do not provide destructors in types derived from this class.
        /// </summary>
        ~DisposeDemo()
        {
            // Do not re-create Dispose clean-up code here.
            // Calling Dispose(false) is optimal in terms of
            // readability and maintainability.

            Dispose(false);   
        }

        #endregion
    }

   
}
Run the project.

Download

3 comments: