Resources » .NET programming » .NET Framework

Explanation of IDisposable interface in C#


Posted Date: 07-Feb-2006  Last Updated:   Category: .NET Framework    
Author: Member Level: Gold    Points: 10


Uses of dispose method in C#. Explanation of IDisposable pattern in .NET. OOPS and the inherent paradigm shifts. Explanation of Destructor, or a Finalize or a Dispose with working examples of each.



Introduction


Prior to object oriented era, developers never had to worry about memory management (if not completely, but most of them certainly did not bothered). Let us take 'C', where there is nothing called an object, everything you ever wanted should be coded from the scratch. Of course, as the time evolved so does the library of 'C'. If you want to store a string you use a character pointer (char *). So memory management happens when the variable goes out of scope. All the problems started when somebody thought they can improve the system. (Eventually we all know the mess we are currently in, let be Java/C# or even C++).

OOPS and the inherent paradigm shifts


With the invent of OOPS (object oriented programming structure), things have changed for the developer. It turned to be more complex for most of the developers (if not all). There were objects which go onto heap, and variables that comfortably sit on the stack. Developers should be wise enough to decide when they want to sit on stack or heap (i don't literally mean developers, but their types/code instead). C++, for that matter, gave much leverage to the developer to create and destroy the objects as per the wish of the developers. A developer can create a new object or delete an existing object. If the developer has to perform some logic when an object is created on the heap they can use a constructor(let me not get into the mess of visibility of the object) and when he wants to perform some logic when an object is deleted, they can use a destructor.

The main problem with this was, If suppose my code (which of course is very well written) landed up on the computer of a user (who obviously doesn't know how to program Micro computers). In the worst case the user buys my code (Its worse not because he bought my code, but he bought it, i mean not free). He expects that my code is of superior quality(which is correct). But due to his lack of programming capabilities (read common sense), he always creates new objects and never deletes those objects. This results in memory leaks and ultimately performance degradation of the system. (He certainly knows whom to blame for this)

Things were going on when one day Microsoft came up with VC++ and MFC (Microsoft Foundation classes), all the worries in the faces of developers vanished and they all jumped with joy. MFC introduced a new concept called Dispose. Microsoft said, “provide Dispose method in all classes for cleaning up the resources along with a destructor. If the user is good, he'll delete the object. If the user is evil, ask him to call Dispose method on that object before the object goes out of scope. If he is worst (than evil) then God save his application.”

This was an instant success. Technologies developed overtime. COM era came and Microsoft introduced an interface called IDisposable. They specified all COM components must inherit from IDisposable. Thus ensuring good programming practice across the industry. Thus started the pattern called IDisposable.

Java, developed by SUN (read Microsoft haters association) did not enforce IDisposable pattern (Understandably). Instead, they introduced automatic memory management. Though Automatic memory management (garbage collection) was not invented in Java (I know some languages which implemented GC much before Java, for e.g., Prolog, Lisp...), it certainly gained ground with Java. Java removed the concept of destructor and introduced a new method called Finalize. Developers have to write the cleanup code in the Finalize method and the GC when executed will call the Finalize method (if available) of the object. There were some problems with this. (I don't want to start a third world war by highlighting the drawbacks of Java as opposed to .Net). So take it that there were some (mysterious) problems with this approach.

Times passed and Microsoft came up with their next generation (as Microsoft specifies) programming platform called .Net (at last, after all the headache we are in .Net). Microsoft followed the (by now very famous) automatic memory management methodologies. Not to forget the new .Net language C#, which was supposedly a clone (mixture is more appropriate word) of C++, Java, Delphi and Visual Basic.(This is because we are dealing with examples in C#). In VC#.Net, (for that matter any .Net language) Microsoft retained the old destructor (from C++) and introduced Finalize method (from Java) and continued their greatest invention, IDisposable (from VC++).

Destructor, or a Finalize or a Dispose


Now, the developer is in dilemma. Which one should he use. A destructor, or a Finalize or a Dispose method?

Theoretically both destructor and Finalize method are same. When compiled a destructor will emit a Finalize method in the MSIL – Microsoft Intermediate Language (I assume, you know somethings about .Net technology). Means, if you have a c++ back ground you would like to write a destructor and if you have a Java background, you would like to use a Finalize method. (It is very much obvious that you cannot have both of them at a single time) so C# provides only destructor syntax to define Finalize also.

GC in .Net is designed in such a way that, it destroys all the objects without any clean up code (destructor) in a single blow. Whereas, it takes two blows to delete an object with destructor.

In plain English, if the clean up code can be called by the user, then GC can blow off the object in a single go.

No language allows the user to call the destructor explicitly and .Net (C#) is also no exception, so you cannot call destructor. Though you can call a Finalize method, it is against the programming best practices to call the Finalize method. So the left out option is to provide a Dispose method which can be called by the user (if he is interested)

So the rule of thumb here (for any .Net language) is, “if you have any clean up code to be performed, provide both Finalize and Dispose methods”. If the user calls Dispose method, thats good for him. Otherwise also you can use the Finalize method to clean up the resources.

Now a question arouses in everyones mind (no points for that). What if the user calls Dispose method. Even then the Finalize method will be called by the GC.
Well, if not programmed well, this could be the case. So, when you are writing code for Dispose method always ensure that you suppress the Finalize method. In C# you can do this by using the SupressFinalize method of GC class. Thus ensuring that only one of the method is called at anytime.

Example


Now, let us look at a simple class which provides both Dispose method and Finalize method (with proper coding) and how it behaves in all scenarios.

/* Code Follows */

using System;

namespace DisposablePattern
{
class Example
{
static void Main()
{
//Start without debugging to see the messages
InvokeClassWithDestructor();
Console.WriteLine("1.");
InvokeClassWithDestructorAndDispose();
Console.WriteLine("2.");
InvokeClassWithDestructorAndDisposeCallingDispose();
Console.WriteLine("3.");
}

private static void InvokeClassWithDestructor()
{
ClassWithDestructor myObj = new ClassWithDestructor();

myObj.Display("This is a sample message for ClassWithDestructor");

//myObj goes out of scope, so GC calls the destructor.
}

private static void InvokeClassWithDestructorAndDisposeCallingDispose()
{
ClassWithDestructorAndDispose myObj = new ClassWithDestructorAndDispose();

myObj.Display("This is a sample message for ClassWithDestructorAndDispose");
myObj.methodName = "InvokeClassWithDestructorAndDisposeCallingDispose()";
//explicitly call dispose (good programming practise)
myObj.Dispose();
//myObj goes out of scope, but GC does not call the destructor.
//as you have already called the dispose
}

private static void InvokeClassWithDestructorAndDispose()
{
ClassWithDestructorAndDispose myObj = new ClassWithDestructorAndDispose();
myObj.methodName = "InvokeClassWithDestructorAndDispose()";
myObj.Display("This is a sample message for ClassWithDestructorAndDispose");

//myObj goes out of scope, so GC calls the destructor.
}
}

class ClassWithDestructor
{
string message;

///
/// Constructor
///

public ClassWithDestructor()
{
message = "From Class With Destructor";
}

///
/// Some method
///

///
public void Display(string information)
{
Console.WriteLine(message);
Console.WriteLine(information);
}

///
/// Destructor
///

~ClassWithDestructor()
{
Console.WriteLine("This is from destructor of ClassWithDestructor");
//release the resources
message = null;
}
}

class ClassWithDestructorAndDispose : IDisposable
{
string message;
public string methodName;

///
/// Constructor
///

public ClassWithDestructorAndDispose()
{
message = "From Class With Destructor And Dispose";
}

///
/// some method
///

///
public void Display(string information)
{
Console.WriteLine(message);
Console.WriteLine(information);
}

///
/// destructor
///

~ClassWithDestructorAndDispose()
{
Console.WriteLine("This is from destructor of ClassWithDestructorAndDispose called from {0}", methodName);
//release the resources
message = null;
}

///
/// inheriting the Dispose method of IDisposable interface
///

public void Dispose()
{
Console.WriteLine("This is from dispose of ClassWithDestructorAndDispose called from {0}", methodName);
//release the resources
message = null;

//comment this to see the fun
GC.SuppressFinalize(this);
}
}
}


Output:
From Class With Destructor
This is a sample message for ClassWithDestructor
1.
From Class With Destructor And Dispose
This is a sample message for ClassWithDestructorAndDispose
2.
From Class With Destructor And Dispose
This is a sample message for ClassWithDestructorAndDispose
This is from dispose of ClassWithDestructorAndDispose called from DestructorAndDisposeCallingDispose()
3.
This is from destructor of ClassWithDestructorAndDispose called from InvokeClassWithDestructorAndDispose()

This is from destructor of ClassWithDestructor

Summary


Using the IDisposable, we can provide the developers with the option to either clean up the code themselves (which saves them some memory and time) or let the garbage collector take the headache in cleaning up the resources.

Please feel free to ask me questions/comments/suggestions or anything.


Did you like this resource? Share it with your friends and show your love!

Responses to "Explanation of IDisposable interface in C#"
Author: sateesh b    22 Mar 2006Member Level: Silver   Points : 0
Tahnks ! Really it is very helpful,


Author: Mirza Asfaar Baig    23 May 2010Member Level: Bronze   Points : 2
Your statements are in conflict with each other..Kindly, clarify..


"GC in .Net is designed in such a way that, it destroys all the objects without any clean up code (destructor) in a single blow. Whereas, it takes two blows to delete an object with destructor."

"In plain English, if the clean up code can be called by the user, then GC can blow off the object in a single go."



Feedbacks      

Post Comment:




  • Do not include your name, "with regards" etc in the comment. Write detailed comment, relevant to the topic.
  • No HTML formatting and links to other web sites are allowed.
  • This is a strictly moderated site. Absolutely no spam allowed.
  • Name:   Sign In to fill automatically.
    Email: (Will not be published, but required to validate comment)



    Type the numbers and letters shown on the left.


    Submit Article     Return to Article Index

    Subscribe to Subscribers
    Awards & Gifts
    Talk to Webmaster Tony John

    Online Members

    Tara Prasad
    More...
    Copyright © SpiderWorks Technologies Pvt Ltd., Kochi, India