.NET Framework 2.0 Performance Inspection Questions - Exception Handling

From Guidance Share

Jump to: navigation, search

- J.D. Meier, Srinath Vasireddy, Ashish Babbar, Rico Mariani, and Alex Mackman


Contents

Do You Catch Exceptions You Cannot Handle?

You should catch exceptions for very specific reasons, because catching generally involves rethrowing an exception to the code that calls you. Rethrowing an exception is as expensive as throwing a new exception.

Check that when your code catches an exception, it does so for a reason. For example, it might log exception details, attempt to retry a failed operation, or wrap the exception in a new exception and throw the outer exception back to the caller. This operation should be performed carefully and should not obscure error details.


Do You Control Application Logic with Exception Handling?

Check that your code does not use exception handling to control the flow of your normal application logic. Make sure that your code uses exceptions for only exceptional and unexpected conditions. If you throw an exception with the expectation that something other than a general purpose handler is going to do anything with it, you have probably done something wrong. You can consider using bool return values if you need to specify the status (success or failure) of a particular activity.

For example, you can return false instead of throwing an exception if a user account was not found in the database. This is not a condition that warrants an exception. Failing to connect to the database, however, warrants an exception.


Do You Use Finally Blocks to Ensure Resources Are Freed?

Make sure that resources are closed after use by using try/catch blocks. The finally block is always executed, even if an exception occurs, as shown in the following example.


  SqlConnection conn = new SqlConnection(connString);
  try
  {
    conn.Open();  // Open the resource
  }
  finally
  {
   if(null!=conn)
     conn.Close();  // Always executed even if an exception occurs
  }


Note C# provides the using construct that ensures an acquired resource is disposed at the end of the construct. The acquired resource must implement System.IDisposable or a type that can be implicitly converted to System.IDisposable, as shown in the following example.


  Font MyFont3 = new Font("Arial", 10.0f);
  using (MyFont3)
  {
      // use MyFont3
  }   // compiler will generate code to call Dispose on MyFont3


Do You Use Exception Handling Inside Loops?

Check if your code uses exceptions inside loops. This should be avoided. If you need to catch an exception, place the try/catch block outside the loop for better performance.


Do You Rethrow Exceptions?

Rethrowing exceptions is inefficient. Not only do you pay the cost for the original exception, but you also pay the cost for the exception that you rethrow.

Rethrowing exceptions also makes it harder to debug your code because you cannot see the original location of the thrown exception in the debugger. A common technique is to wrap the original exception as an inner exception. However, if you then rethrow, you need to decide whether the additional information from the inner exception is better than the superior debugging you would get if you had done nothing.

Personal tools