I know that in Java, if an exception is caught by a catch clause and its catch block throws an exception, control would pass throw the associated finally block (if any) before the thread is terminated. This does not appear to be the case in C#, however.
It is possible to almost mirror this behavior in C# is by putting a try-finally statement inside the try block of the try-catch statement with the catch block that throws the exception, but that would be a problem if, for example, the finally block is supposed to contain code that disposes a Stream Writer that is supposed to log the exception.
Is there a clean way to achieve java-like try-catch-finally exception handling behavior in C#?
Here's an update with the requested sample code:
StreamWriter writer = new StreamWriter("C:\\log.txt");
try
{
throw new Exception();
}
catch (Exception e)
{
writer.WriteLine(e.Message);
throw e;
}
finally
{
if (writer != null)
{
writer.Dispose();
}
}
Add that code to a console application, run it, let the re-thrown exception go unhandled, attempt to delete C:\log.txt. You won't be able to, because control never passed through the finally block. Also, if you add a breakpoint to some line inside the finally block you will see that it doesn't get hit. (I'm using VS2005).
As far as I know, the only way to force control to pass through the finally block is if the re-thrown exception is handled by the catch block of an enclosing try block (if you took the code above and placed it inside the try block of another try-catch statement).
If the exception is not caught and is allowed to terminate the application, as in the sample code I provided, control won't pass through the finally block.
In Java it would. In C#, at least based on what I have seen, it would not.
In the .NET Framework, when an exception occurs, the system will determine what if anything is going to catch that exception before any finally
blocks execute. Depending upon various application settings, an attempt to throw an exception which will not be caught may kill the application instantly, without giving any finally
blocks (or anything else) a chance to run.
If one wraps the Main
method, as well as each thread, in
try
{
...
}
catch
{
throw;
}
then any exception which is thrown within the try
block will get caught. Even though it will be immediately re-thrown, any nested finally
blocks will execute before the catch
. There are some cases where this is desirable behavior; there are other cases where one may wish to e.g. perform some special logging if an exception isn't going to be caught (in some cases, the information one wishes to log may be destroyed if the finally
blocks get a chance to run first). Within C#, there isn't any way to vary one's actions based upon whether an exception is going to be caught, but in VB.NET there are some ways via which that can be done; a VB.NET assembly which makes calls to C# code can give that code a way of knowing whether any exceptions thrown by an inner method will propagate out to the vb.net wrapper without being caught.