Tuesday, February 16, 2010

Best Exception Handling Practises

Best Practices for handling exceptions

1) Exception is an expensive process, for this reason, you should use exceptions only in exceptional situations and not to control regular logic flow.

For example:

void EmpExits ( string EmpId)
{
//... search for employee
if ( dr.Read(EmpId) ==0 ) // no record found, ask to create
{
throw( new Exception("Emp Not found"));
}
}

The best practice is :

bool EmpExits ( string EmpId)
{
//... search for Product
if ( dr.Read(EmpId) ==0 ) // no record found, ask to create
{
return false
}
}

2) Avoid exception handling inside loops, if its really necessary implement try/catch block surrounds the loop.

3)Adopt the standard way of handling the exception through try, catch and finally block. This is the recommended approach to handle exceptional error conditions in managed code, finally blocks ensure that resources are closed even in the event of exceptions.

For example:

SqlConnection conn = new SqlConnection("...");
try
{
conn.Open();
//.some operation
// ... some additional operations
}
catch(¦)
{
// handle the exception
}
finally
{
if (conn.State==ConnectionState.Open)
conn.Close(); // closing the connection
}

4)Where ever possible use validation code to avoid unnecessary exceptions .If you know that a specific avoidable condition can happen, precisely write code to avoid it. For example, before performing any operations checking for null before an object/variable can significantly increase performance by avoiding exceptions.

For example:

double result = 0;
try
{
result = firstVal/secondVal;
}
catch( System.Exception e)
{
//handling the zero divided exception
}

This is better then the above code

double result = 0;
if(secondVal >0)
result = firstVal/secondVal;
else
result = System.Double.NaN;

5)Do not rethrow exception for unnecessary reason because cost of using throw to rethrow an existing exception is approximately the same as creating a new exception and rethrow exception also makes very difficult to debug the code.

For example:

try
{
// Perform some operations ,in case of throw an exception
}
catch (Exception e)
{
// Try to handle the exception with e
throw;
}

6)The recommended way to handle different error in different way by implement series of catch statements this is nothing but ordering your exception from more specific to more generic for example to handle file related exception its better to catch FileNotFoundException, DirectoryNotFoundException, SecurityException, IOException, UnauthorizedAccessException and at last Exception.

7) .NET errors should be capture through SqlException or OleDbException.
•Use the ConnectionState property for checking the connection availability instead of implementing an exception.

•Use Try/Finally more often, finally provides option to close the connection or the using statement provides the same functionality.

•Use the specific handler to capture specific exception, in few scenarios if you know that there is possibility for a specific error like database related error it can be catch through SqlException or OleDbException as below.

try
{ ...
}
catch (SqlException sqlexp) // specific exception handler
{ ...
}
catch (Exception ex) // Generic exception handler
{ ...
}
8) When creating user-defined exceptions, you must ensure that the metadata for the exceptions is available to code executing remotely, including when exceptions occur across application domains. For example, suppose Application Domain A creates Application Domain B, which executes code that throws an exception. For Application Domain A to properly catch and handle the exception, it must be able to find the assembly containing the exception thrown by Application Domain B. If Application Domain B throws an exception that is contained in an assembly under its application base, but not under Application Domain A's application base, Application Domain A will not be able to find the exception and the common language runtime will throw a FileNotFoundException. To avoid this situation, you can deploy the assembly containing the exception information in two ways:
a) Put the assembly into a common application base shared by both application domains
- or -
b)If the domains do not share a common application base, sign the assembly containing the exception information with a strong name and deploy the assembly into the global assembly cache.

9) In most cases, use the predefined exceptions types. Define new exception types only for programmatic scenarios. Introduce a new exception class to enable a programmer to take a different action in code based on the exception class.

10)Do not derive user-defined exceptions from the Exception base class. For most applications, derive custom exceptions from the ApplicationException class.

11)Include a localized description string in every exception. When the user sees an error message, it is derived from the description string of the exception that was thrown, rather than from the exception class.

12)Use grammatically correct error messages, including ending punctuation. Each sentence in a description string of an exception should end in a period.

13)Provide Exception properties for programmatic access. Include extra information in an exception (in addition to the description string) only when there is a programmatic scenario where the additional information is useful.

14) Throw an InvalidOperationException if a property set or method call is not appropriate given the object's current state.
Throw an ArgumentException or a class derived from ArgumentException if invalid parameters are passed.

Its recommend to use "Exception Management Application Block" provided by Microsoft. It is a simple and extensible framework for logging exception information to the event log or you can customize to write the exception information to other data sources without affecting your application code and implemented all best practices and tested in Microsoft Lab.