Demystify Garbage Collection in C#: Part 4

Welcome to the Garbage Collection article series. In this series, I have been dealing with Garbage Collection in C#. If you are interested iin learning the nitty-gritty of the Garbage Collection then I recommend you visit the following previous articles:
 
In today's article, we will learn one very important concept of Garbage Collection called "Finalize dispose pattern". Let me start with my small personal experience. In our organization, we (developer people, better to say poor developer people at least in my case) conduct telephonic technical sessions as a first round screening test when we need .NET developers.
 
Once there were a need for people for senior (5+ experience) .NET Developers and as usual, we were conducting interview sessions by telephone and I also was in that team. One of my favorite questions was what is the basic idea of "what is the finalize dispose pattern and how to implement it?".
 
And the result is that 95% of developers (with 5+ years of experience) have never implemented the finalize dispose pattern and those who have implemented it don't properly know the need for it. They implemented it because their bosses/managers told them to. A few of them said they always use GC.Collect() in each page of an application when the page is closed. Hmm, what an idea? Collect garbage in each page unload event.
 
OK, I hope that after reading this article you will learn why the finalize dispose pattern is really needed and what its advantage is.
 
Why the finalize disposal is needed when the garbage collector automatically manages memory
 
Yes, this is one big question. Now think about the garbage collector. When is it run? If there is a shortage of memory for an application and more memory is needed. Now if we destroy an object that was created by ourself then the chances of the Garbage Collection executing will be very low.
 
And that's why we will learn the mechanism to destroy our own object after its operation uses the finalize dispose pattern.
 
What is Finalize dispose?
 
It is nothing but a pattern or mechanism to clear the object from memory when we finish an operation associated with that specific object.
 
Before going into the explanation of the finalize dispose pattern I would like to discuss a little about the IDosposable interface. This interface needs to be implemented in a class where we want to implement the finalize dispose pattern.
 
IDisposable interface
 
This is a very interesting interface; why? It contains only one method, Dispose(), and that method needs to be implemented in the class.
 
How to implement the IDisposable interface
 
It is very simple. (But the truth to be told, I struggled a bit in my first-time implementation). In the following example, we will create one class that will contain a few managed and unmanaged resources. And we will implement the Dispose() method and within Dispose () we will clear the resources. Have a look at the following code.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Linq;  
  6. using System.Windows.Forms;  
  7. using System.Data.SqlClient;   
  8. namespace WindowsForm  
  9. {  
  10.     public partial class Form1 : Form  
  11.     {  
  12.         public Form1()  
  13.         {  
  14.             InitializeComponent();  
  15.         }  
  16.         private void Form1_Load(object sender, EventArgs e)  
  17.         {  
  18.         }  
  19.         private void button1_Click_1(object sender, EventArgs e)  
  20.         {  
  21.             Garbage g = null;  
  22.             for (int i = 0; i < 10000; i++)  
  23.             {  
  24.                 g = new Garbage();  
  25.                 g.Dispose();  
  26.             }  
  27.         }         
  28.     }  
  29.     public class Garbage: IDisposable   
  30.     {  
  31.         public String name = String.Empty;  
  32.         SqlConnection con = null;  
  33.         public Garbage()  
  34.         {  
  35.             name = "Sourav Kayal";  
  36.             con = new SqlConnection();  
  37.         }  
  38.         ~Garbage()  
  39.         {  
  40.             Dispose(false);  
  41.         }  
  42.         protected virtual void Dispose(bool disposing)  
  43.         {  
  44.             if (disposing)  
  45.             {  
  46.                 //Free managed resource here  
  47.                 name = null;  
  48.             }  
  49.             //Free unmanaged resource here  
  50.             con = null;  
  51.         }   
  52.         public void Dispose()  
  53.         {  
  54.             Dispose(true);  
  55.             GC.SuppressFinalize(this);  
  56.         }   
  57.     }  
How it executes
 
Let's think first about iteration within a for loop.
  1. In a for loop the first object for the Garbage class will be created using g =new Garbage() statement.
  2. The constructor of the Garbage() class will execute and will initialize two resources (one string and one connection object).
  3. Then within the Main() function the next line g.Dispose() will execute. Then the Dispose function with no argument will execute.
    1. public void Dispose()  
    2. {  
    3.       Dispose(true);  
    4.       GC.SuppressFinalize(this);  
    5. }  
    Here we are seeing it's calling again the overloaded version of another Dispose function() with the argument true.
     
  4. Then the following function will be executed:
    1. protected virtual void Dispose(bool disposing)  
    2. {  
    3.      if (disposing)  
    4.      {  
    5.           //Free managed resource here  
    6.           name = null;  
    7.       }  
    8.       //Free unmanaged resource here  
    9.       con = null;  
    The if we clean/release managed resources and outside of the if condition we will clear unmanaged resources.
     
  5. Then control will return again in the "void Dispose()" function and will execute the following line:
    1. GC.SuppressFinalize(this); 
    This ensures that the Finalize/Destructor will be suppressed and will not execute for this object.
     
    I have profiled this program with the CLR profiler and here is the object by age graph.
     
    image3.gif
     
    Here, we are seeing that most objects are being created in generation 0 and it is a sign of good practice.
When we need to implement a finalize dispose pattern.
 
It's not mandatory for a finalize dispose pattern to be implemented in all classes. Implement the finalize dispose pattern when the class is dealing with many unmanaged resources.


Recommended Free Ebook
Similar Articles