Summary

When used properly, exceptions can add to an application's stability and robustness. The .NET Framework and the CLR have made exception handling mandatory, but at the same time, exceptions have never been easier to use and extend. In the interest of better exception and error handling, the following guidelines should prove beneficial:

  • Because it is so easy to handle and generate exceptions, great care should be taken to make sure you know when not to rely on exceptions. If, for example, an object can be tested for an invalid condition (such as null) to avoid having an exception raised, then do so. Suppose that you have an object that must be closed to free up the resources it was using, but closing an already closed object resulted in an exception. You would be faced with the following choices:

       if(conn.State != ConnectionState.Closed)
          conn.Close();
            or
       try {
         conn.Close();
       }
       catch(InvalidOperationException ex) {
         //Do something with the error or ignore it.
       }
    

    The second method requires little processing when the exception is not generated (the connection is not already closed). The first method would be preferred if it was found that the connection was already closed most of the time. (Avoid the creation of an exception instance.)

    This might involve redesigning (or designing) your class so that you can avoid an exception. Take, for instance, the FileStream class:

    class FileRead {
        void Open() {
            string file = "myfile.txt";
            if(!File.Exists(file))
                return;
            FileStream stream = File.Open(file, FileMode.Open);
            int b = 0;
    
            // ReadByte returns -1 at EOF
            while ((b = stream.ReadByte()) != -1) {
                // Do something.
            }
        }
    }
    

    This class has been designed so that the exception that will be raised if an attempt to open a file that does not exist or the user does not have permission to look can be avoided.

  • Throw exceptions in rare, exceptional, conditions. Remember that constructing an exception, although it provides invaluable information, is not cheap. You could have code like this:

    int sum = 0;
    int [] array = new int[]{1,2,3,4,5} ;
    i = 0;
    try
    {
        while(true)
        {
            sum += array[i++];
        }
    }
    catch(Exception e)
    {
    }
    

    However, this code is relying on exceptions for flow control, and that is not recommended. It would work and the compiler wouldn't generate a warning, but it would be considered bad programming practice.

  • If you have multiple catch blocks, order the exception handlers in order of most specific to least specific.

  • As the catch block for an exception becomes less specific, it might be harder to decide what to do with the exception. Remember that it might be appropriate to just rethrow the exception. This can only be done inside of a catch block. It is done by specifying a throw with no expression, like this

    throw;
    
  • All of the exception classes defined in the .NET class libraries are named with the word “Exception” at the end of the class name—for instance, ApplicationException, SystemException, and FileNotFoundException. To make your code more readable, it is recommended that your custom exception classes also follow this convention.

  • If a user-defined exception could possibly cross AppDomain boundaries or if the exception is to be passed remotely, then make sure that the metadata associated with the class (the Assembly) is available in each AppDomain in which the exception is referenced. If this is not the case, then another exception FileNotFoundException could be generated. Making sure the assembly is available might require modification of the search path (Appbase property or AppDomain.BaseDirectory) for assemblies in the AppDomain or installation of the assembly in the global assembly cache (GAC).

  • Do not define user-defined exceptions based on the Exception class. Use the class ApplicationException as a base for all user-defined exceptions.

  • Use the exception classes in the library whenever possible and when using the predefined exception classes it makes clear the error that has occurred. If the application is littered with generic Exceptions being thrown, it is hard to determine the error or exception that has occurred. At the same time, having too many user-defined exceptions can also make the code hard to read.

  • In C# and C++, make sure that at least three constructors are defined for each user-defined exception. These three allow a specific error message to be assigned on construction, an inner exception to be assigned to an exception (in the case of multiple exceptions), and both an error message and an inner exception. The definition should look like this:

    public class CustomException : ApplicationException {
        CustomException() {... }
        CustomException(string message) {... }
        CustomException(string message, Exception inner) {... }
    }
    
  • Use a localized description string for exceptions, especially if users will see this exception description.

  • Use correct grammar and punctuation for exception messages.

  • Throw an InvalidOperationException if the object's state is not appropriate for the operation at hand.

  • If any of the arguments are out of range or otherwise invalid, throw an ArgumentException.

  • When deciding on where to throw an exception, remember that the stack trace that is built for you begins where the exception is thrown rather than where the exception was created.

  • Throw exceptions rather than return HRESULTS or other types of error codes.

  • Make it so that throwing an exception has no side effects. Clean up intermediate results when throwing exceptions.

  • Supply and use helper functions to help build an exception where appropriate. This is especially true if building an exception is especially complex or if the operations that are required to build an exception are repeated often.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.223.123