views:

430

answers:

5

Assume you have the following code:

Instead of doing:

Try
    '
    ' Initialize some objects
    '

    '
    ' do something that fails
    '

    '
    ' Clean up-code that gets not reached because exception
    '
Catch e As Exception
    '
    'Clean up initialized objects
    '

    Throw e
End Try

I would like to do:

Try
    '
    ' Initialize some objects
    '

    '
    ' do something that fails
    '
Catch e As Exception
    Throw e
Finally
    '
    'Clean up initialized objects
    '
End Try

So my simple question is: In case of an exception is the finally block reached even if there is a throw some lines before?

[EDIT] Thanks for your fast answers.

In first line there will be NullReference-, COM- and FileNotFound-Exceptions I think.

Ok, I will go for this code:

Try
    '
    ' Initialize some objects
    '

    '
    ' do something that fails
    '
Catch e As Exception      ' or just "Catch"??        
    Throw
Finally
    '
    'Clean up initialized objects
    '
End Try

All the best!

Inno

+12  A: 

So my simple question is: In case of an exception is the finally block reached even if there is a throw some lines before?

Yes. The Finally block is always1) executed and exists precisely for clean-up. In your code, remove the Catch block, it does nothing. Worse, it actually destroys the stack trace because you don’t re-throw the original exception, you throw a new one.

If you really need a Catch block that then re-throws the exception, use the following:

Catch e As XyzException
    ' … do some stuff. '
    Throw
End Try


1): Caveat emptor: there are some exceptions such as StackOverflowException (how fitting …) which require special attention and may not trigger the Finally block. Handling them correctly is usually quite difficult.

Konrad Rudolph
Konrad - Finally is not always executed. It will not get executed when you have an OutOfMemoryException for instance.
Pete OHanlon
@Pete: right, but these are specific edge cases (but I should have mentioned them).
Konrad Rudolph
@Pete: Don't you mean StackOverflowException. It is quiet easy to make a test where finally is run in case of an OutOfMemoryException.
Brian Rasmussen
@Brian: have you done a test? If so, I’ll change my posting to `SOE`. This one really cannot be recovered – `OOME` doesn’t make as much sense. I don’t have .NET installed on my Mac though so I can’t test it myself.
Konrad Rudolph
@Konrad: I can't say if an OOME will ever prevent a finally block from running, but I haven't heard that before. It is however, easy to construct a case where it will run, so Pete's point is not strictly correct. SOE on the other hand will take down the runtime so as far as I am aware that will always prevent finally blocks from running.
Brian Rasmussen
@Brian: The Reliability Best Practices page on MSDN suggests that OOME, SOE, TAE and AppDomain unloads can all prevent the `finally` block from running. Some can be mitigated by using constrained execution regions, but in the case of SOE you need to use the `ExecuteCodeWithGuaranteedCleanup` method instead. http://msdn.microsoft.com/en-us/library/ms228970.aspx
LukeH
@Luke: Thanks for the update and the link. I wasn't aware of OOME could do this. However, it is not the same as "it will not be executed when you have an OOME", which was what I was trying to clarify.
Brian Rasmussen
A: 

Yes it does, finally is executed in any case. (there are only few exceptions - Response.Redirect and some cases with multithreading)

Restuta
+4  A: 

No, it is NOT guaranteed to run. There are certain exceptions - for example StockOverflowException and OutOfMemoryException - where the execution of a finally block is not guaranteed.

Maximilian Mayerl
A: 

In almost all cases, a Finally will execute in a Try/Catch block (notable exceptions including when a StackOverflowException or OutOfMemoryException occur). I am curious though, why you didn't try this out for yourself. A valuable way to learn things is to actually try them out for yourselves - after all, you could end up accepting an answer that is wrong or misleading, and you will labour under this falsehood from that point on.

Pete OHanlon
I tried this out but my debugger stopped at the throw. I read the documentation and didn't find a hint for my question. I asked this questions to get answers belonging directly to my question and belonging indirectly to it (like hints like "finally is under special circumstances not executed").
Inno
A: 

NOTE: System.Environment.FastFail method was kill current process/thread immediatly, without execute finally sections.

kazuk