Exception handling best practices

Excellent exception handling is must for any app for excellent user experience and it is an essential trait of an excellent C# developer.

Tips for Exception handling best practices

Always validate public method parameters and raise appropriate exceptions

If you accept any erroneous input in the method argument, and when external clients use the API, then later on it becomes very expensive to fix the issue.

Never ever allow erroneous argument in the public method of class. Validate extensively and raise ArguementException or ArgumentNullException as appropriate. See below code sample.

Design class/interface such that there is no need to raise an Exception for common scenarios

Raising an exception is a costly operation under the hood. And when class API is designed such that it guarantees not to raise an exception, this improves application performance tremendously, if API is frequently used.

Example: Refer int.TryParse pattern. Also refer below sample code.

Exception Handling Best Practices
Exception Handling Best Practices

Types of Exceptions to be raised from your code

Below types of Exceptions you should raise from your code –

ArgumentException, ArgumentNullException, ArgumentOutOfRangeException, InvalidOperationException.

.NET framework reserved exceptions such as NullRefenceException, OutOfMemoryException, IndexOutOfRangeException should not be raised.

Do not raise generic Exception (sadly Microsoft’s own code samples follow this practice).

Consider creating custom exception as a last option. And when a custom exception is defined it must be marked with Serializable attribute so that they can cross AppDomain and COM boundaries.

Maintain stack trace

Stack trace of exception must be maintained unless there is strong reason to erase stack trace.

Use exception filters as far as possible to log exceptions and preserve stack trace.

Use “throw;” statement instead of “throw ex;”, later erases the stack trace.

Dispose of resources you no longer need

Once you are done with the disposable objects or COM objects or native un-managed resources just dispose them off in the finally block. Refer my other post that mentions about memory leaks in .NET.

Avoid suppressing exception without taking any action

When you suppress exception, it becomes very difficult to find and resolve issues. Consider logging exception to log file (or to some centralized place such as database or windows event log).

Log files can be used for issues debugging and fixing app crash type of scenarios. Log the full stack trace and not just error message.

Also when user is interacting with UI (example clicking OK button) and there is no response (because application suppresses an exception), it results into frustration. Hence you should notify user about errors encountered.

Usually a well tested UI will never display errors to user unless there is some issue, such as database is down.

Have a localization strategy for exception messages

There may not be any need to localize every single exception message in your application. However the error messages that are targeted for end user, must be localized.

In your executable always subscribe to AppDomain’s UnhandledException event.

This ensures that you log an exception into log file or somewhere useful location for later post-martam debugging.

Subscribe to FirstChanceException

Subscribe to FirstChanceException to know problematic areas of your application that might be causing performance degradation.

It is also possible that any 3rd party libraries used might be degrading application performance by raising lot of First Chance Exceptions. This is the way to find out.

Ensure that you refactor your code not to raise First Chance Exception unless absolutely necessary.

Subscribe to WPF Dispature’s unhandled exception events

This helps to notify user about any uncaught exceptions, and also gives you a chance to recover from them. See the code sample below for reference.

Code Sample