I have a simple test code that works as expected in .NET3.5, but the same code behaves completely different on a project created with .NET4.5.1.
class Program { static void Main(string[] args) { try { string a = null; var x = a.Length; } catch (Exception ex) { throw; } finally { Console.WriteLine("This is the finally block."); } Console.WriteLine("You should not be here if an exception occured!"); } }
First of all, the weird thing is that the NullReferenceException type exception is completely ignored in .NET4.5.1 when running the compiled RELEASE exe file. Basically, no error is thrown, although in debug mode the exception is thrown.
Second of all (and most importantly), if the error is different than NullReferenceException, such as “index out of range” for example, then the exception is actually thrown as expected, but the “finally” block is never hit which is not the behavior I expected from the try-catch-finally block. I tried in different machines, and had 2 other colleagues of mine also trying and we all got the same result.
It seems that either I never really understood the try-catch-finally block, or .NET4.5.1 handles exception in a different way, or there is some bug with .NET4.5.1. All I know is that the code above works in .NET3.5 as I expected it to work, but I don’t seem to get the same result when running it in .NET4.5.1 .
Can someone shed some light on this? I am at a total loss right now.
EDIT Based on Eric J answer I was able to resolve the NullReferenceException issue. Since I asked 2 questions, I'll create a new thread for the second question. Try-Catch-Finally block problems with .NET4.5.1
C# 4 Language Specification § 8.9. 5: If the finally block throws another exception, processing of the current exception is terminated. Unless it is a ThreadAbortException , then the whole finally block will be finished first, as it is a critical section.
It is a reserved keyword in C#. The finally block will execute when the try/catch block leaves the execution, no matter what condition cause it. It always executes whether the try block terminates normally or terminates due to an exception. The main purpose of finally block is to release the system resources.
The keyword finally is used to identify a statement or statement block after a try - catch block for execution regardless of whether the associated try block encountered an exception, and executes even after a return statement.
Yes, it is not mandatory to use catch block with finally.
string a = null; var x = a.Length;
In RELEASE mode, the jitter (just in time compiler) is able to prove that x
is never referenced, so is able to remove the assignment.
In DEBUG mode, the jitter does not perform that optimization.
To force the exception to be thrown, do something with x
(e.g. as @Henk suggests in the comments, WriteLine(x)
).
EDIT
Eric Lippert noted in the comments
...I am as surprised as anyone that the jitter would elide a string length instruction that could throw. That seems wrong to me...
The jitter optimization may be overly-aggressive.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With