Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine if executing in finally block due to exception being thrown

Is it possible to determine if code is currently executing in the context of a finally handler as a result of an exception being thrown? I'm rather fond of using the IDisposable pattern to implement entry/exit scoping functionality, but one concern with this pattern is that you might not necessarily want the end-of-scope behavior to occur if an exception occurs in the body of the using. I'd be looking for something like this:

public static class MyClass
{
    public static void MyMethod()
    {
        using (var scope = MyScopedBehavior.Begin())
        {
            //Do stuff with scope here
        }
    }
}

public sealed class MyScopedBehavior : IDisposable
{
    private MyScopedBehavior()
    {
        //Start of scope behavior
    }

    public void Dispose()
    {
        //I only want to execute the following if we're not unwinding
        //through finally due to an exception:
        //...End of scope behavior    
    }

    public static MyScopedBehavior Begin()
    {
        return new MyScopedBehavior();
    }
}

There are other ways I can accomplish this (pass a delegate to a function that surrounds the call with particular behavior), but I'm curious if it's possible to do it using the IDisposable pattern.


Actually, this has apparently been asked and answered before here. It's possible to detect in a very hackish sort of way. I wouldn't actually use that technique, but it's interesting to know that it's possible.

like image 513
Dan Bryant Avatar asked Jul 21 '10 16:07

Dan Bryant


People also ask

Does finally execute if exception thrown?

A finally block always executes, regardless of whether an exception is thrown.

What happens if exception is thrown in finally block?

The "finally" block execution stops at the point where the exception is thrown. Irrespective of whether there is an exception or not "finally" block is guaranteed to execute. Then the original exception that occurred in the try block is lost.

Will finally be executed without exception?

A finally block is always get executed whether the exception has occurred or not. If an exception occurs like closing a file or DB connection, then the finally block is used to clean up the code.

Does finally execute if no exception is thrown Java?

The finally block executes regardless of whether an exception is thrown or caught.


3 Answers

The means of accomplishing this that I've seen require an extra method:

public static void MyMethod()
{
    using (var scope = MyScopedBehavior.Begin())
    {
        //Do stuff with scope here
        scope.Complete(); // Tells the scope that it's good
    }
}

By doing this, your scope object can track whether it's disposing because of an error, or a successful operation. This is the approach taken by TransactionScope, for example (see TransactionScope.Complete).

like image 66
Reed Copsey Avatar answered Oct 09 '22 11:10

Reed Copsey


As a side point, IL allows you to specify SEH fault blocks that are similar to finally but are entered only when an exception is thrown - you can see an example here, about 2/3rds down the page. Unfortunately, C# doesn't expose this functionality.

like image 15
thecoop Avatar answered Oct 09 '22 11:10

thecoop


I was looking for something similar for unit testing - I have a helper class I use to clean up objects after a test run and I want to keep the nice, clean 'using' syntax. I also wanted the option of not cleanup up if the test failed. What I came up with is to call Marshal.GetExceptionCode(). I don't know if this is appropriate for all cases, but for test code it seems to work fine.

like image 7
dmo Avatar answered Oct 09 '22 11:10

dmo