Saturday, August 6, 2016

Memory management using Finalize and Dispose Method.

In this article I will be talking about one of the most important topic related to memory management in .net. We know that managing the memory is the primary concern of any application. So to help the programmers focus on implementing their functionality .net introduced automatic memory management using Garbage Collector. Garbage collection is the heart of .net application. But Garbage collector has a limitation that it can clean up only managed resources. So now the question is what is a managed resource and what is an unmanaged resource.
Managed Resource:-Managed resource means anything that can be managed by CLR(any code that uses CLR ,this can be managed code written in c# or c++).CLR handles memory management for such resources and automatically clears the memory when not needed.
Unmanaged Resources: -Unmanaged resources are generally c or c++ code, libraries or dlls.These are called unmanaged because coder has do the memory management (allocate memory for the object and clean the memory after the object is no longer being used.).These can be file handles, database connections ,etc.

So now when we have a basic idea of Managed and Unmanaged resources, We will move further towards our main topic how to implement memory management for unmanaged resources. CLR provides some help in releasing memory claimed by unmanaged resources. For clearing unmanaged resources we have a virtual method finalize in System.Object Class.
Finalize Method:- Object Class does not provide any implementation to the Finalize method. Unless a class derived from object class overrides the finalize method garbage collector cannot mark it for finalization. Garbage collector maintains a finalization queue for all the objects in the Heap whose finalization method code must run before Garbage Collector can run to reclaim their memory. Garbage Collector automatically calls the finalize method but it is not sure when Garbage Collector will run and call finalize method.

Now I will show you how to implement Finalize Method .Finalize is a virtual method of Object Class. It does not have any access modifier. We cannot call the finalize method directly as there is no keyword like finalize. So to use finalize we need to create a destructor. Destructor is a special method that has same name as class name with a tilt prefixed before it. Destructor cannot have any parameters. At compile time the destructor is converted to Finalize() Method. Below is the sample code for the same.
using System; namespace FinalizeDemo { class Program { static void Main(string[] args) { FinalizeDemo d = new FinalizeDemo(); d = null; Console.ReadLine(); } } class FinalizeDemo { public FinalizeDemo() { Console.WriteLine("Object Created"); } ~FinalizeDemo() { Console.WriteLine("Destructor Called."); } } }

Now we have added a destructor for the class ,lets verify whether it has created a finalize method for the same. So for this purpose I will be using ILSPY .In ILSPY we will browse the exe created .Below is the snapshot for the same .Here we can see the constructor but not the destructor. Now click on the Finalize method, you will see the destructor. So destructors are converted to Finalize method at compile time. Now we will run the above code .Even though we assign null to object still it’s not garbage collected. To see the destructor being called run the above application through command prompt. See the below snapshot for the same.




Note: Even though we assigned null to the object we cannot predict when memory will be de-allocated. So to make the memory de-allocated immediately we can call GC.Collect() method.
In .net we have one more way to clear unmanaged memory.
Dispose Method:- Dispose method is also used to unmanaged resources like connections ,file ,etc. This method belongs to IDisposable interface. IDisposable interface has only one method i.e. Dispose. To clear all the unmanaged resources held by a class we need to inherit that class from IDisposable interface and implement Dispose method.We have to write all cleanup code in DisposeMethod. Whenever we want to free the resources held by that object we can call the Dispose method.
using System; namespace FinalizeDemo { class Program { static void Main(string[] args) { FinalizeDemo d = new FinalizeDemo(); d.Dispose(); d = null; Console.ReadLine(); } } class FinalizeDemo:IDisposable { public FinalizeDemo() { Console.WriteLine("Object Created"); } ~FinalizeDemo() { Console.WriteLine("Destructor Called."); } public void Dispose() { Console.WriteLine("Dispose Method Called"); } } }

But there is a problem in this approach. If the user forgot to call the Dispose method, there will be memory leak. To overcome this problem its recommended to use Dispose and Finalize together. So that if user forgot to call Dispose method ,Garbage Collector can call the Finalize Method and clear all the memory held by the object.Below is the code snippet to implement Dispose and Finalize .Instead of writing the same logic in Dispose method and destructor ,we will be creating a Dispose Method that accepts a Boolean parameter. This method can be called from destructor or from Dispose () method.
using System; namespace FinalizeDemo { class Program { static void Main(string[] args) { FinalizeDemo d = new FinalizeDemo(); d.Dispose(); d = null; Console.ReadLine(); } } class FinalizeDemo:IDisposable { private bool Disposed = false; public FinalizeDemo() { Console.WriteLine("Object Created"); } ~FinalizeDemo() { Console.WriteLine("Destructor Called."); Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public void Dispose(bool disposing) { if(!Disposed) { if (disposing) { Console.WriteLine("Called From Dispose"); //Clear all managed resoures here } else { //Clear all Unmanaged resources here } Disposed = true; } } }

Here we have taken a Boolean variable Disposed =false. Now we have 2 Scenarios 1)If user calls Dispose method:-Here we are checking whether object has been disposed or not .Now when we call this method from Dispose method of IDisposable interface then we pass true. In if block we will write all clean up code and then outside it we will set the Disposed variable to true.
2)If User Forget to Call Dispose Method:-In this case Destructor will call the Dispose Method with false and control will go to else block inside Dispose method .Here we will write all clean Up code.
.Net introduce using block to take care of calling Dispose method ,if a class is implementing IDisposable interface. So it’s a good practice to create object within using block.