Daily Knowledge Drop
When using a class which implements IDisposable
inside a try-catch-finally
block, if an exception is thrown in what order are the Dispose and catch block executed?
The order is:
- Dispose method on the class implementing IDisposable
- Catch block
- Finally block
Logically this makes sense, as the IDisposable
class is out of scope when the catch
block is being executed. The lowered code can also be viewed to get an even deeper understanding of how these two features fit together.
Example
Consider the following class which implements IDisposable:
public class DisposableClass : IDisposable
{
public DisposableClass()
{
Console.WriteLine($"In Constructor of {nameof(DisposableClass)}");
}
public void Dispose()
{
Console.WriteLine($"In Dispose of {nameof(DisposableClass)}");
}
}
As it implements IDisposable, it can be used with the using
statement:
try
{
// declare instance of the disposable class
using var disposableInstance = new DisposableClass();
throw new Exception("Exception or dispose?");
}catch(Exception ex)
{
Console.WriteLine("An exception occurred");
}
finally
{
Console.WriteLine("In the finally block");
}
Executing the above, results in the following output:
In Constructor of DisposableClass
In Dispose of DisposableClass
An exception occurred
In the finally block
Dispose called before the catch block.
Lowered
Looking at the lowered
code (generated using sharplab.io) it becomes more obvious as to why this is the sequence of events:
internal static class <Program>$
{
private static void <Main>$(string[] args)
{
try
{
DisposableClass disposableClass = new DisposableClass();
try
{
throw new Exception("Exception or dispose?");
}
finally
{
if (disposableClass != null)
{
((IDisposable)disposableClass).Dispose();
}
}
}
catch (Exception)
{
Console.WriteLine("An exception occurred");
}
finally
{
Console.WriteLine("In the finally");
}
}
}
internal class DisposableClass : IDisposable
{
public void Dispose()
{
Console.WriteLine("Disposing DisposableClass");
}
}
The using
statement is converted into its own try-finally
block, with the Dispose being called inside the finally.
Looking at the above code, it make entire sense that the sequence of events is:
Constructor
of the disposable class- The first
finally
block is called, and theDispose
method is invoked - The
catch
block is called, and the exception is handled - The second
finally
block is called
Notes
The sequence of events in this scenario was not something I had considered before - but thinking through what each block of code does (as well as executing the sample code, and looking at the lowered code), the sequence of events makes sense, and is as one would probably expect. However, it is good to get confirmation and gain a better understanding of how one's code might operate under the hood.
References
Daily Drop 151: 01-09-2022
At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.
The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.On This Page