EluciusFTW
EluciusFTW

Reputation: 2615

How to be explicit about NOT throwing an exception?

This might be a broad question, but recently I ahve wondered about the following: In our C# backend we have many places that wrap some code in a try/catch block, specifically calls to external WcF services. Some of these calls are crucial for the application so in the catch block we log the error and rethrow, like:

catch(Exception ex)
{
    _logger.Error("Some good error message");
    throw ex;
}

On the other hand there are services we allow to fail, but we still want to log the error, so they look like:

catch(Exception ex)
{
    _logger.Error("Some good error message");
}

Now reading the code of team members I can not be sure if they forgot to throw or if this is the intended behaviour.

Q: Is there a way, resp. what is the default way, to explicitly NOT rethrow (without including a comment in the code).

I have considered something like this:

catch(Exception ex)
{
    _logger.Error("Some good error message");
    NotThrowingHereOnPurpose();
}

// ...
// and further below a private method
// ...

private void NotThrowingHereOnPurpose(){}

Upvotes: 3

Views: 1473

Answers (4)

EluciusFTW
EluciusFTW

Reputation: 2615

I actually found another way that kind of includes what other have suggested here, but uses a built in feature: exception filters. I was free to modify the example given in here to illustrate this:

public void MethodThatFailsSometimes()
{
    try {
        PerformFailingOperation();
    } 
    catch (Exception e) when (e.LogAndBeCaught())
    {
    }
}

and then one could have two extension methods on Exception, say LogAndBeCaught and LogAndEscape like so:

public static bool LogAndBeCaught(this Exception e)
{
    _logger.Error(@"Following exception was thrown: {e}");
    return true;
} 

public static bool LogAndEscape(this Exception e)
{
    _logger.Error(@"Following exception was thrown: {e}");
    return false;
} 

Upvotes: 0

Yoh Deadfall
Yoh Deadfall

Reputation: 2781

It's an opposite solution to dasblinkenlight's answer. Instead of notifying others that the exception mustn't be rethrown it would say that it must be.

If you only want to log it then use the Error method as usual. Otherwise, you can write an extension method for your logger to log and throw exceptions.

The method would take the catched exception and rethrow it using the ExceptionDispatchInfo class. The ExceptionDispatchInfo is used to rethrow the exception with the original stack trace information and Watson information. It behaves like throw; (without the specified exception).

public static void ErrorAndThrow(this ILogger logger, string message, Exception exception)
{
    var exceptionInfo = ExceptionDispatchInfo.Capture(exception);

    logger.Error(message);
    exceptionInfo.Throw();
}

And use it this way:

try
{
}
catch (Exception ex)
{
    // ex would be rethrown here
    _logger.ErrorAndThrow("Some good error message", ex);
}

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

One approach that may be useful here is to change the way of invoking the code that you explicitly allow to fail in such a way that it does not look like a try/catch block at all.

For example, you could write a helper method that does error reporting, and call it with actions expressed as lambdas:

void InvokeFailSafe(Action action, Action<Exception> onFailure = null) {
    try {
        action();
    } catch (Exception e) {
        if (onFailure != null) {
            onFailure(e);
        }
    }
}

Now instead of try/catch you would write this:

InvokeFailSafe(
    () => {
        ... The code that may fail
    }
,   exception => _logger.Error("Some good error message: {0}", exception)
);

or like this, if you don't want anything logged:

InvokeFailSafe(
    () => {
        ... The code that may fail
    }
);

If you code things this way, there would be no doubts about a missing throw statement.

Upvotes: 3

Harsh
Harsh

Reputation: 3751

Q: Is there a way, resp. what is the default way, to explicitly NOT rethrow (without including a comment in the code).

Ideal way would be not to catch a generic exception. Now, to throw or not that entirely depends on your case. You need to understand that Exception handling is used when you know what to do in case an exception occurs. So, only specific exceptions should be handled. Catching exceptions without knowing what you are catching will change the behavior of your application.

Now reading the code of team members I can not be sure if they forgot to throw or if this is the intended behaviour.

This is something the author of the code can explain to you. But here is a learning to take from this. Your code should be self explanatory. In specific cases where you are unable to express yourself with the code, add a meaningful comment.

You can check this link for better understanding.

Upvotes: 0

Related Questions