Resource consumption may impede your application's performance metrics or may even prevent it from working at all.
Add try/catch blocks in the constructor to release unmanaged resources.
Finding the Solution
I created a small application to test the using statement's behavior and to investigate different ways to release the unmanaged resources acquired by the failed constructor.
Here's the code for the application:
static void Main(string[] args)
{
using(A a = new A()) // A : IDisposable implements the dispose pattern
{ //point1
. . .
} //point2
. . .
}
And here's the stripped IL code:
.locals init ([0] class MyApplication.A a)
IL_0000: newobj instance void MyApplication.A::.ctor()
IL_0005: stloc.0
.try
{
IL_0006: leave.s IL_0012
} // end .try
finally
{
IL_0008: ldloc.0
IL_0009: brfalse.s IL_0011
IL_000b: ldloc.0
IL_000c: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0011: endfinally
} // end handler
The IL code shows that, according to the C# specification, if an exception is thrown between point1 and point2, Dispose() is called on the instance of A and necessary clean up is performed. This clean up includes the release of unmanaged resources. When the exception was thrown from the A() constructor, the above finally block was not executed. This is why the code should be updated to release the allocated resources that can be leaked.
Initial Attempts
My first strategy was to write an explicit try/catch block around the using statement and, from there, call a.Dispose(). Of course, this garnered a CS0246 compile time error because "the type or namespace name ‘a’ could not be found." Therefore, I decided to declare the a variable before the try block. The code compiled, but resulted in a NullReferenceException exception because "Object reference not set to an instance of an object."
Checking if a is not null before calling a.Dispose() eliminates the runtime error, but also abolishes the call to a.Dispose() because a, in this case, will definitely be null. Any other exercises that involved moving try\catch blocks and instantiating type a did not help either. Thus, it became evident that the mix of an explicit try\catch block was not getting along with the implicit try\finally block when both of them call a.Dispose().
An alternative solution to the problem was to add a try/catch block inside the A() constructor to guard places that may throw an exception. This guarding method releases previously acquired unmanaged resources in the constructor's catch block after the point of failure. It was a solution. I released unmanaged resources inside the failed constructor, rethrew the exception, and used the try\catch explicit block around the using statement.
http://www.devx.com/dotnet/Article/39023