You may have been taught that when handling exceptions, each method is considered separately. That is, since your internal method has a try...finally , any exception will first call finally , and then will look at try above. This is not true.
From the ECMA CLR specification (ECMA-335, I.12.4.2.5 Exception Handling Overview):
When an exception occurs, the CLI looks for an array for the first protected block, which
- Protects the region, including the current instruction pointer, and
- It is a catch handler block and
- Whose filter wants to handle the exception
If no match is found in the current method, a search is made for the calling method, etc. If no match is found, the CLI will delete the stack trace and interrupt the program.
If a match is found, the CLI moves the stack back to the point it just found, but this time it calls the finally and fault handlers. Then it starts the corresponding exception handler.
As you can see, the behavior is 100% consistent with the specification.
- Find a protected block -
try in SomeOperation - Does it have a catch handler block? No.
- Find the protected block in the calling method -
try in Main - Does it have a catch handler block? Yes!
- Can a filter handle an exception? The filter is evaluated (disclaimer: this does not mean that all filters in the protected unit will always be evaluated - itβs not a problem if the filter has no side effects, which it really should not, of course), and the result is yes.
- Go back onto the stack and execute all finally and fault handlers
finally in Main not part of this, of course - it will be executed when execution exits the protected block, regardless of the exception.
EDIT:
Just for completeness - it has always been so. The only thing that has changed is that C # now supports exception filters, which allows you to monitor the execution order. VB.NET supports exception filtering from version 1.
Luaan Aug 02 '16 at 12:39 on 2016-08-02 12:39
source share