c# "finally" block that only runs on exceptions

BCS picture BCS · Feb 10, 2009 · Viewed 8.3k times · Source

Edit: I have looked at the answers code: NONE of them do what I want (I've checked). It would seem that there is no way to do what I want in native c#. I guess that's not a disaster just a shame given that .NET does support it (see accepted answer).

Thanks all.


I have c# code (part of a test framework that will never be run except under a debugger) like this who's point it to avoid actually catching the exception as that makes debugging the code in the unwound part of the stack a royal pain.

Bool bad = true;
try
{
   MightThrow();
   bad = false;
}
finally
{
   if(bad) DoSomeLoggingOnFailure();

   //// Does not catch!!!! 
   //// exception continues to unwind stack.

   //// Note that re throwing the exception is NOT
   //// the same as not catching it in the first place
}

is their a better way to do this?

A solution would have to behave exactly like that under the debugger with regards to un-caught exceptions. It would have to result in the only one first chance exception and the debugger breaking at the point that the exception was originally thrown, not in a catch block.

Specifically I need the debugger on un-caught exceptions to stop a in side MightThrow.

The following doesn't work because it fails to have the debugger break in the correct place

try { ... } catch { throw; }

And this doesn't work because it loses stack info (and also breaks in the wrong place).

try { ... } catch(Excption e) { throw e; }

I known that in D I could use a scope(failure) block

Answer

Greg Beech picture Greg Beech · Feb 10, 2009

So, in .NET what you're asking for is theoretically possible, but it's not going to be easy.

CIL actually defines five types of exception handling block! The try, catch and finally ones you're used to in C#, and two others:

  • filter - similar to a catch block but can run arbitrary code to determine whether it wants to handle the error, rather than just matching on type. This block has access to the exception object, and has the same effect on the exception stack trace as a catch block.

  • fault - similar to a finally block, however it is only run when an exception occurs. This block does not have access to the exception object, and has no effect on the exception stack trace (just like a finally block).

filter is available in some .NET languages (e.g. VB.NET, C++/CLI) but is not available in C#, unfortunately. However I don't know of any language, other than CIL, that allows the fault block to be expressed.

Because it can be done in IL means not all is lost, though. In theory you could use Reflection.Emit to dynamically emit a function that has a fault block and then pass the code you want to run in as lambda expressions (i.e. one for the try part, one for the fault part, and so on), however (a) this isn't easy, and (b) I'm unconvinced that this will actually give you a more useful stack trace than you're currently getting.

Sorry the answer isn't a "here's how to do it" type thing, but at least now you know! What you're doing now is probably the best approach IMHO.


Note to those saying that the approach used in the question is 'bad practice', it really isn't. When you implement a catch block you're saying "I need to do something with the exception object when an exception occurs" and when you implement a finally you're saying "I don't need the exception object, but I need to do something before the end of the function".

If what you're actually trying to say is "I don't need the exception object, but I need to do something when an exception occurs" then you're half way between the two, i.e. you want a fault block. As this isn't available in C#, you don't have an ideal option, so you may as well choose the option that is less likely to cause bugs by forgetting to re-throw, and which doesn't corrupt the stack trace.