bimbima

Daily life experience of ayurvedic medicines, complementary therapies.

C-Sharp: How and When to use Dispose Pattern ?

As we know, In dotnet program we don't need to delete(Cleanup) objects by our self because dotnet program is a managed code and there is garbage collector to do cleanups very efficiently for unused objects when required.

But in some cases you need to free some unmanaged resource(Objects which uses unsafe handles like file, COM objects, Native resource etc) before garbage collector release it.

For example you are doing some operation on a file using FileStream object and you are not closing or disposing it and again you are trying to use this file some where else then it might give you exception "The process cannot access the file 'C:\temp.txt' because it is being used by another process." if you are not closing or disposing file object because garbage collector will not clean it immediately. Refer below code snippet.

        private void ReadFile()
        {
            FileStream stream = new FileStream(@"C:\temp.txt", FileMode.Open);
            //Do some task
        }
 
        private void ReadAgain()
        {
            FileStream stream = new FileStream(@"C:\temp.txt", FileMode.Open);
            //Do some task
        }

When you call ReadFile() and ReadAgain() it will give you exception in ReadAgain() because GC has not cleaned stream object in ReadFile() immediately and FileStream uses unmanaged resource.

To avoid this Garbage Collection problem you have to call FileStream's Dispose or Close methods like this.

        private void ReadFile()
        {
            FileStream stream = new FileStream(@"C:\temp.txt", FileMode.Open);
            //Do some task
            stream.Dispose(); // or Close() method
        }

To provide more robust and exception safety code MS has defined Dispose Design pattern (Implementation of pattern will be discussed in next section). Objects which are using dispose pattern should be used in try . finally blocks, because suppose you are using a unmanaged resource or handle in your program and an exception occurred then you resource will not free if you are not calling dispose method in finally block.

Here is example for FileStream  object which is using Dispose Pattern

        private void ReadFile()
        {
            FileStream stream = null;
            try
            {
                stream = new FileStream(@"C:\temp.txt", FileMode.Open);
                //Do some task
                
            }
            //Catch here for exception handling
            finally
            {
                if (stream != null)
                {
                    stream.Dispose();
                }
            }
            
        }

Note: In above example you can call close method also, it calls dispose method internally.

Always do cleanups  for unmanaged resource in finally block.

In dotnet programming language like c#, compiler provide more clean method to use this pattern by using "using" keyword. if you are using "using" keyword then c# compiler automatically generates code to call Dispose method  of objects which are implementing IDisposable interface as given below.

        private void ReadAgain()
        {
            using (FileStream stream = new FileStream(@"C:\temp.txt",
                FileMode.Open))
            {
                //Do some task
            }
        }

Note: You can use "using" only with objects which are implementing IDisposable interface otherwise use them using try. finally block and do cleanup in finally block only.

Implementing Dispose pattern in your class

Here is sample to implement class using dispose pattern. For using dispose pattern you have to implement IDisposable interface.

    class MyReader : IDisposable
    {
        private Stream _resource;
        private bool _disposed;
 
        // The stream passed to the constructor 
        // must be readable and not null.
        public MyReader(Stream stream)
        {
            if (stream == null)
                throw new ArgumentNullException("Stream in null.");
            if (!stream.CanRead)
                throw new ArgumentException("Stream must be readable.");
 
            _resource = stream;
 
            _disposed = false;
        }
 
        ~ MyReader()
        {
            Dispose(false);
        }
        public void Dispose()
        {
            Dispose(true);
 
            // Use SupressFinalize in case a subclass
            // of this type implements a finalizer.
            GC.SuppressFinalize(this);
        }
 
        public void Close()
        {
            Dispose(true);
        }
        protected virtual void Dispose(bool disposing)
        {
            // If you need thread safety, use a lock around these 
            // operations, as well as in your methods that use the resource.
            if (!_disposed)
            {
                if (disposing)
                {
                    if (_resource != null)
                        _resource.Dispose();
                    Console.WriteLine("Object disposed.");
                }
 
                // Indicate that the instance has been disposed.
                _resource = null;
                _disposed = true;
            }
        }
    }

In above example i have used stream object which used file handle and implements IDisposable interface. Stream object _resource dispose method will be called when you will call dispose or close methods explicitly or you will use MyReader with using keyword.

Note: It is recommended that if you are using any object in your type which implements IDisposable or you are using any unmanaged resource then use Dispose pattern for efficient cleanups.