In .Net land, classes that hold onto resources resources that need to be cleaned up after usage should impliment IDisposable. These resources can include database connections, input or output streams, and unmanaged resources such as window handles.
There are a number of classes in the System.* namespaces that implement IDisposable. When you use a class that impliments this interface, it is your responsiblity to call .Dispose() when done with the class. When you author a class that holds onto valuable resources such as those listed above, you should impliment IDisposable and call Dispose on any composite objects your class is referencing that impliment IDisposable, plus do any other cleanup that is needed to prevent memory leaks such as releasing event handlers. Remember, if one of your objects handles an event from another object, that other object has a reference to your object and therefore garbage collection will not occur on your object (memory leak).
Microsoft tried to make it easy to use IDisposable objects in C# by adding the using block to the language:
using(SomeDisposableClass x = new SomeDisposableClass())
{
//some work here
}
The code snippet above will always call x.Dispose() when the code execution leaves the block. Pretty handy, right. Well, not really. What is not obvious about this code block is that it silently eats exceptions. The following code block does the exact same thing as the using block:
SomeDisposableClass x = new SomeDisposableClass();
try
{
//some work here
}
finally
{
x.Dispose();
}
Any exception is just lost. It is never handled. This is very, very bad. When writing code that uses IDisposable, *never* use using. At very least do something like this:
SomeDisposableClass x = new DisposableClass();
try
{
//some work here
}
catch(Exception ex)
{
throw ex;
}
finally
{
x.Dispose();
}
Now why would Microsoft give us such a dangerous language feature in C#? I have read that it was to encourage developers to dispose of resources. I don’t buy it. In my mind, there are three alternatives to the current using block that would have been better. The first is simple, just have using throw any exception it encounters!
My second idea is to create a using block with a catch:
using(SomeDisposableClass x = new SomeDisposableClass())
{
//some work here
}
catch(Exception ex)
{
throw ex;
}
In my imagination, the statement above always creates a finally in the IL that disposes of x.
My third idea is to modify try/catch/finally to handle IDisposable types:
try(SomeDisposableClass x = new SomeDisposableClass())
{
//some work here
}
catch(Exception ex)
{
throw ex;
}
The only wrinkle in this third idea is that a programmer may choose to write a finally block a do some custom logic to dispose of the x object. I am sure the compiler could detect this condition and handle it acordingly. All in all, I like me second idea the best.
I think it is much more dangerous to silently eat exceptions than it is to create memory leaks. Memory leaks just cause computers to get slow or crash. Silent exceptions are not only difficult to debug, but could be causing data corruption that is not detected during the development and testing phases of the software life-cycle. Put it this way: Memory leaks are George Bush evil, data corruption is Hitler + Stalin evil. I would happily welcome Microsoft modifying or deleting the using statement from the C# language.