Archive

Archive for the ‘GarbageCollection’ Category

Destructor – Finalize & IDispose

October 3, 2010 1 comment

This post is about techniques on how managed/unmanaged resources used/referenced by objects can be released. There are two ways to do this. They are namely,

1. Implement IDisposable

2. Implement Destructor (Finalize) for object.

This post describes how both gets implemented and what are the pros n cons of both ways.

Destructor & Finalize :

Destructor in managed code can be written in similar way as unmanaged code.

 class TestClass
{
    ~TestClass()  // destructor implementation
    {
        // free resources
    }
}

When destructor is written in managed code, it ultimately translates into following code post compilation :

protected override void Finalize()
{
    try
    {
        // free resources here
    }
    finally
    {
        base.Finalize();
    }
}

(So this means both destructor & Finalize are same in managed context.)

How destructor works :

When reference count becomes zero for the object which implements destructor then that object is marked for collection and object is put into the finalization queue. When garbage collector start collecting the memory, at that time destructor for the objects in the finalization queue will be called. When destructor is called then unmanaged resources can be freed and object memory is collected.

IDispose :

IDispose is basically .net framework interface which defines the method to release the allocated resources. Inside the interface method implementation should be present to release the resources.

How IDispose work :

Let’s consider following code to understand how IDispose and destructor work in tandem. In following example “TestClass” implements IDisposable and also implements destructor. This code uses managed resource StreamReader and unmanaged some Integer pointer which needs to be freed before object is freed after it’s use.

    public class TestClass: IDisposable
    {
        // Pointer to an external unmanaged resource.
        private IntPtr intPointer;
        // managed resource
        System.IO.StreamReader stream;
        // Track whether Dispose has been called.
        private bool disposed = false;

        // The class constructor.
        public TestClass()
        {
            this.intPointer = /* assign some integer pointer*/;
            stream = new System.IO.StreamReader(@"C:\Test.txt");
        }

        // Implement IDisposable.
        public void Dispose()
        {
            Dispose(true);
            // as dispose has already been called supress finalizer
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if(!this.disposed)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if(disposing)
                {
                    // Dispose managed resources.
                    stream.Close();
                }

                // dispose unmanaged resources here.
                intPointer = IntPtr.Zero;

                // Note disposing has been done.
                disposed = true;

            }
        }

        // destructor
        ~TestClass()
        {
            Dispose(false);
        }
    }

Dispose method with private accessor is being called from both interface Dispose method as well as destructor. When Dispose is called, first managed resource is freed and after that unmanaged resource is freed. Thus both managed and unmanaged resources are freed. After clearing the resources, GC.SupressFinalize is called so that the object is removed from finalize queue.

Now the question is when IDisposable and destructor are doing the same thing then why two separate things are required. Answer of this question lies in the nature of the execution of both these implementation.

Difference between Descturctor-Finalize & IDisposable :

Destructor is not deterministic way of freeing the resource. When object with destructor is marked for garbage collection, it will be put inside the finalization queue. Whenever garbage collector runs, object inside the finalization queue will free the resources. Because time when the garbage collector will run is not sure, it can not be predicted when resources will be freed.

IDisposable is deterministic way of freeing the resource. IDisposable is useful when some shared resources or some high memory consuming resources needs to be freed. Calling the dispose on the object will ensure that resources are freed immediately (however memory associated to the object may not get collected until garbage collector runs).

Some Finer points about Destructor-finalize & IDisposable :

Destructor – Finalize :

  1. Finalize is not a good option to use when shared resources / memory consuming resources needs to be freed because of it’s non deterministic nature.
  2. Releasing the resources using Finalize is costly from performance point of view. Why implementing Finalize is costly is explained here (last para) in MSDN.
  3. In finalize method, finally block has been put and it calls the Finalize on base class also. This makes sure that all the hierarchy of objects release the resources properly.
    IDisposeable :
  1. As mentioned above, IDispose can only free the resources and can not free the memory consumed by the object itself.
  2. Onus of calling Dispose method on the object still remains with the user. Just implementing IDisposable will not make sure that all resources are released properly. Dispose method will not be called automatically by framework except object is called with “using”.
  3. Calling dispose is not thread-safe.
  4. It is better to consider implementing try..finally block inside the dispose method because if during the execution of dispose method any exception occurs there is no way left to free the resources.

References :

MSDN

Advertisements