Home .NET Put in a good word for poor Dispose

Put in a good word for poor Dispose

by admin

A little bit about releasing resources in .Net.
warning : The text below is simply a retelling in its own words of long-known information that is available online at Russian and English languages.
What to do when you want to free unmanaged resources in .Net? You can put the resource release code in the finallysection and thisis the easiest way. It’s not very fancy, but it’s guaranteed to work and has no pitfalls:

DBConnection conn = new DBConnection();
try
{
conn.Open();
//...
}
finally
{
conn.Close();
}
* This source code was highlighted with Source Code Highlighter

Let’s make the task more difficult. We wrote a library classthat works with unmanaged resources. By the law of meanness (or big numbers, whatever you prefer), apart from the gurus, it will be used by shit-coders. Who will easily forget to call the method to free unmanaged resources. And then they will spit on the poorly written BY YOU library.
So, I want to write my class in such a way, that the method which frees the resources (whether it’s managed or unmanaged)will be automatically called by garbage collector in case ifuser forgets to call it himself.
To free unmanaged resources, it’s proposed to use the IDisposable interface with one single function, Dispose, which should free the resources. And the main task here is not to write thisfunction, but to write the code so that this function is necessarily called.
We have two cases :
1) The user has called a method that frees the resources himself
2) The user did not ask for resources to be freed and this should be done by GC
The first option looks something like this :

using (MyClass x = new MyClass())
{
x.SomeMethod();
//...
}
* This source code was highlighted with Source Code Highlighter

or so :

MyClass x;
try
{
x = new MyClass();
x.SomeMethod();
//...
}
finally
{
if (x != null )
x.Dispose();
}
* This source code was highlighted with Source Code Highlighter

The second option looks like this :

MyClass x = new MyClass();
x.SomeMethod();
//...
* This source code was highlighted with Source Code Highlighter

Let’s think about how to implement the MyClass class itself and its Dispose method to make our code work in all these cases? Let’s list the requirements that lie on the surface :
1) the Dispose method must not crash ifit is called several times in a row (foolproofing)
2) the Dispose method should not be called from GC if it is called explicitly (and, accordingly, should be called from GC if the user did not call it himself).
These two considerations are what made the proposed implementation of the MyClass class to have a disposed variable (to be able to distinguish between an already released class and a not released class), a destructor (to call the Dispose method from GC) and finally a wrapper over the Dispose function – a function with the boolparameter Dispose(boolmanual)(to distinguish between a manual call to Dispose and an automatic one). Oh yeah. And you need to distinguish manual call from automatic call to disable destructor call with GC.SuppressFinalize(this);method.
So we get the class like this (just copying from msdn):

public class MyResource: IDisposable
{
private bool disposed = false ;
//implementation of the IDisposable interface
//don't make this function virtual
//and do not overlap in the descendants
public void Dispose()
{
Dispose( true ); //release was called manually
GC.SuppressFinalize( this ); //we don't want GC to call the destructor
}
//destructor
~MyClass()
{
Dispose( false ); //GC required resource release by calling the destructor
}
//release resources
private void Dispose( bool manual)
{
if (! this disposed)
{
if (manual)
{
//release resources
//...
//in other words - call Dispose method
//for all managed member variables of a class
//this only needs to be done for a manual call to Dispose,
//because otherwise Dispose will call GC for them
}
//release unmanaged resources
//...
disposed = true ;
}
}
}
* This source code was highlighted with Source Code Highlighter

That’s it. There’s a slight complication to this code if you inherit from the MyClass class (there you need to ensure that the Dispose method is called by the parent class, by overriding the Dispose(bool) method). But it’s not that complicated anymore.

You may also like