Exception handling is the technique of handling runtime errors in your application code. Basically, you have two categories of exceptions: Exceptions that are generated by the application and those that are generated by the runtime. Exceptions should be handled with care -- you should have a good idea of how exceptions should be handled and when they are needed to be handled in your code. In this post, I will present a few tips and best practices for working with exceptions in C#.

The base class for all exceptions in .NET is Exception. All exception classes in the exception hierarchy derive directly or indirectly from this class. The ApplicationException and SystemException classes are derived from the Exception class. The Common Language Runtime (CLR) throws an instance of a type that is derived from SystemException when an error occurs at runtime. Note that you should never catch SystemException or throw an instance of SystemException in your application's code.

When creating custom exception classes, always derive from the Exception class and not from the ApplicationException class. One of the reasons for this is that an instance of ApplicationException is thrown by the application and never by the runtime. In throwing an instance of ApplicationException in your code, you would just increase the call stack without adding much value.

It is a bad design approach to use exception handling to return information from a method. If you are returning exception data from your method, your class design is wrong and should be revisited. Note that exceptions are bubbled up to the higher level in the method call hierarchy and it is not a good practice to handle exceptions in all the layers of your application. You should handle an exception as higher up in the call hierarchy as you can -- you can consume an exception in the presentation layer and display appropriate messages to the user to notify the exact error that has occurred.

Re-throwing an exception is needed when you would like to rollback a database transaction. It is a good practice to use specific exceptions like FileNotFoundException, IOException, etc. when writing exception handlers and then a general catch block at the end with the Exception class. This would ensure that you get to know the exact error or the specific error that has occurred. The MSDN states: "The ApplicationException class does not provide information as to the cause of exceptions. In most scenarios, instances of this class should not be thrown. In cases where this class is instantiated, a human-readable message describing the error should be passed to the constructor."

You should use try - catch blocks to handle exceptions and use a finally block to clean up the resources used in your program. The try block would contain code that might raise an exception, the catch block will be used to handle the exception thrown inside the try block and the finally block will be used to deallocate any resources the program has used. Note that the finally block is guaranteed to be executed irrespective of whether an exception has occurred or not. Hence, finally block is the best place in your code for cleaning up the resources your program has used.

The code snippet below shows how the "using" statement can be used to dispose resources. Note that the "using" statement is an equivalent of try - finally block.