Question

Browsing the net for better fault handling in C#, I've com across the following to implementation strategies. The first one is natural to me, while the other implementation I'm not certain what its advantages are?

1)

static void Fault(Action protectedBlock, Action faultHandler)
{ 
    try
    {
        protectedBlock();
    }
    catch
    {
        faultHandler();
        throw;
    }
}

2)

static Action Fault(Action protectedBlock, Action faultHandler)
{
    return () =>
    {
        try
        {
            protectedBlock();
        }
        catch
        {
            faultHandler();
            throw;
        }
    };
}

Is 2) the preferred strategy when developing higher order functions in C#?

And, I am wondering, if one approach is more efficient than the other.

Was it helpful?

Solution

The second case is like a Faultable Action Factory. Where you pass in a delegate of what you want to do, protectedBlock, and a delegate of what to do when an Exception occurs, faultHandler. The actions are returned wrapped in a try/catch structure as an aggregate Action. My problem with both these methods is no Exception is actually being caught so who ever is going to catch your throw has no information on which to act.

The difference in execution between the 2 is when they actually execute. The 1st will be executed when it's called. The 2nd will execute whenever the returned Action is called. I don't think the efficiency difference would be significant.

OTHER TIPS

(2) can be further composed, whilst (1) just runs. But neither are exactly "functional" as Action is not a function (compare with Func<A, R>).

So with (2) you could do:

Fault(someAction, Fault(firstTryFaultHandler, lastDitchFaultHandler))();

...and get expected behavior. That doesn't work with (1)

In C#, approach 2 can be confusing. A caller might use "Fault(a, b);" expecting a and possibly b to be called. Instead, a lambda is created, returned and discarded. In other words nothing is done.

Regarding efficiency, approach 2 is a bit wasteful if most of your calls are of the form "Fault(a,b)();", i.e. you invoke the lambda immediately. In this situation, you don't need a lambda.

For these reasons, I would prefer approach 1. If you need to defer execution, you can introduce a lambda explicitly "() => Fault(a, b)".

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top