Did you know: Find out if an exception was thrown from a finally block!

This is a big biggie for me, because it enables a much nicer syntax for a lot of stuff. But first, let us show this:

using(new ExceptionDetector())
{
	if(new Random().Next(1,10)%2 == 0)
          throw new Exception();
}

How can you tell, from the ExceptionDetector, if an exception was thrown or not? Well, conventional wisdom, and what I thought about until 15 minutes ago, says that you can't. I want to thank Daniel Fortunov, for teaching me this trick:

public class ExceptionDetector : IDisposable
{
    public void Dispose()
    {
        if (Marshal.GetExceptionCode()==0)
            Console.WriteLine("Completed Successfully!");
        else
            Console.WriteLine("Exception!");
    }
}
Amazing!

Print | posted on Wednesday, June 20, 2007 12:47 AM

Feedback


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 2:32 AM inoodle

Ooooo nice one.
That puts:
using(new UnitOfWork()) {} back on the table - instead of Within.UnitOfWork(anon delegate etc).


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 3:56 AM Alex Henderson

That's some sweet stuff :) how come I haven't heard of it until now!


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 4:08 AM Derik Whittaker

Ok,

What am i missing? In what scenario is this needed?


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 4:10 AM Jeff Brown

Oh neat! Mind that I think it can be fooled... What happens if your using statement appears within an exception handler? Will you be able to tell whether the exception occurred within or outside the exception handler?


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 4:11 AM Jeff Brown

Doh! Meant within the using statement.


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 7:23 AM Ayende Rahien

@inoodle,
Absolutely!


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 7:30 AM Ayende Rahien

@Derik,
It enable this code:

using(new Transaction())
{
/// blah
}

Where the transaction can decide if it wants to commit or rollback based on the exception status.


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 7:54 AM Jeff Perrin

Derik,

Previously to do a "using" with a transaction you had to do something like this:

using(Transaction t = new Transaction()){
//important stuff
t.VoteToCommit();
}

Using this technique it looks like you don't need the VoteToCommit() call, which is good because I always forgot to add that, and then spent hours debugging why my tables weren't being updated.


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 10:20 AM Gokhan

Then why don't you write the code in the post using the use case, in the first place?

There's so much going on in comments on this site, all the time, and you write 187 posts a day, average. When wife and kid start to complain, I'll give them your e-mail :)


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 12:21 PM Jeff Brown

@Jeff Perrin,
Yep, I've forgotten Transaction commits too. Wouldn't it be nice to have Smalltalk blocks in C# instead of these clunky control structures? Anonymous delegates and even lambdas don't quite cut it. Oh well.

Still, the exception detecting using trick will be very useful indeed... My only concern is that its behavior may surprising to the unwary.


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 12:58 PM Jeff Brown

One last thought...

Is this hack portable? What will Mono do? I assume it doesn't necessarily implement its exception handling using Win32 SEH. Therefore I wouldn't be too surprised if the Marshal.GetExceptionCode() method were unimplemented or not meaningful...


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 1:36 PM Stefan Wenig

ayende, this is what MSDN lib says:

GetExceptionCode is exposed for complier support of structured exception handling (SEH) only. If called before an exception is thrown, this method returns 0xCCCCCCCC.

Ok, so firstly, == 0 seems to be wrong. Then, which exception? The last exception on this thread? The innermost exception in the current scope? The exception in the innermost scope? You'd have to make and test a whole lot of assumptions here.

What about portability? Mono?

I have to say I'd rather write VoteToCommit() than build on such weak assumptions...


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 3:38 PM Bill Pierce

I'm a bit slow to catch on as well. Is the intention of ExceptionDectector to allow you to dispose differently depending on wether or not an exception was thrown? I would need a use case to more fully understand this feature.

@inoodle:
I would contend that Within.UnitOfWork is a much clearer syntax, even with delegate { } tacked on the end.

@Jeff Perrin:
What if you do not want to implicitly commit the transaction if no exception is thrown? The current functionality of SqlTransaction is to implicitly Rollback if no Commit was issued. I would prefer more descriptive syntaxt like using(Transaction trans = new Transaction(CommitStyle.Implicit)) { }

What is my feeble brain missing?


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 5:17 PM Ayende Rahien

You aren't missing much. That is the intent of the code.
The ideas behind With.Transaction, etc are to handle the case of thrown exception, so having a good way to handle that is very nice.


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 10:12 PM John Rusk

I wonder why Microsoft did not use this for System.Transactions? Do they know something we don't? Did they simply not think of it? Or, did they discard it because they felt that a more explicit syntax was easier for us to understand?


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 10:26 PM Ayende Rahien

I would go with the more explicit syntax reason


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/20/2007 11:36 PM Bevan Arps

Provided this is reliable (something I'm not yet convinced of), this is going to simplify a whole bunch of things in my codebase.

Interestingly, you could do this in a supported way in Delphi, and I was talking to a friend recently to see if it was possible in .NET.

I wonder, does referencing Marshal introduce any odd dependencies that wouldn't normally be present? If so, this could explain why MS didn't use it themselves in System.Transactions.


Gravatar

# re: Did you know: Find out if an exception was thrown from a finally block! 6/25/2007 2:32 PM inoodle

Ah, just spotted a potential issue for me at least...
Marshal.GetExceptionCode() won't work under asp.net medium trust.
Back to delegates :)

Comments have been closed on this topic.