Exception handling

This article is part of our exception handling article series.
Learn more about exception handling

Do not catch exceptions

An exception is handled when the containing method can deliver the promised result. A method called GetUser(int userId) is only successful when it returns a user. If you have a try/catch block in that method, the exception is only handled if you can return a user from the catch block. If you can't, avoid having a try/catch in the method.

Remember that exceptions are for exceptional cases, which basically means cases that your team did not consider when building the application. Since none of you thought of them, how on earth could you handle them? If you did think of them, why did you not prevent them? Either way, adding a try/catch do not help.

Most, if not all, .NET libraries have specific integration points that you can use to catch and log unhandled exceptions.

Exceptions to the rule

There are however some exceptions from the above rule.

Enrich exceptions

Exceptions give you an insight into why an error occurred. However, for some exceptions, the exception message isn't helpful. If you, for instance, have used the Dictionary<TKey, TValue> class you have most likely stumbled on its exception saying:

The given key was not present in the dictionary.

The message evidently states what's wrong but give no clue to which key is missing, making it near to impossible to correct the error. What you could do is to catch the exception and add information to it:

try
{
    var user = _myProperties[userId];
    //do something
}
catch (KeyNotFoundException ex)
{
    ex.Data["UserId"] = userId;
    throw;
}

Wrap exceptions

When an exception is leaving a specific application layer like the data layer or business layer it can make sense to wrap the exception in a less specific one.

try
{
    var user = repository.GetById(userId);
    // some processing
}
catch (DbException ex)
{
    throw new DataException("Failed to contact the database for user " + userId, ex);
}

What's important here is that the original exception is included as an inner exception. We get all the information into the log by doing so and with a business relevant exception message.

Conclusion

Avoid cluttering your code base with try/catch just to be able to log errors. Use your favorite .NET libraries integration point instead.

Use try/catch to enrich exceptions or wrap them to get business related information into the exceptions. It makes it so much easier to understand why an exception was thrown.