Chapter 12. Exception Handling

Exception handling helps applications trap and respond in a predictable and robust manner to exceptional events. This enhances the correctness of an application, which naturally improves customer satisfaction. Exception handling is an important ingredient of a robust application, but it is often an afterthought. You should proactively consider exception handling as an integral part of the application design and include it in all aspects of application planning and development. Conversely, treating exception handling as an afterthought leads to poorly implemented solutions for exception handling and a less robust application.

What is an exception? Exceptions are events, often indicating an error, that alter the normal flow of execution within an application. Exceptions are categorized as system exceptions or application exceptions. System exceptions are raised by the Common Language Runtime (CLR) and include null-reference, out-of-memory, divide-by-zero, and stack overflow exceptions. Some exceptional events are detected by application logic, not by the run time. Application exceptions are useful in these circumstances. Application exceptions, considered user-defined exceptions, are thrown by the application, not by the CLR. As an example, constructors that fail are not always detectable by the CLR. In addition, constructors implicitly return void, which prevents returning an error code. For these reasons, throwing an application exception in the failed constructor is the best solution to notify the application and user.

It may sound silly to say it like this, but I’ll say it anyway: Exceptions are for exceptions! Exception handling is not a substitute for transfer of control or a goto statement. Exceptions are expensive when compared with conventional methods of transferring control, which are relatively inexpensive. Whenever possible, applications should preempt an exception with error checking and avoid the elevated cost of exception handling. For example, you can perform data validation and return an error code, if incorrect values can cause exceptions. Data validation and, if necessary, returning an error code are undoubtedly cheaper performance-wise than raising an exception.

Overuse of exceptions makes code harder to read and maintain. Errors that frequently occur should not be handled with exception handling, but with error codes or returns. Remember that exceptions should be reserved for exceptional events.

An Exception Example

A common exception is caused by dividing by zero. Integer division, where the divisor is zero, triggers a divide-by-zero exception. (However, floating-point division by zero does not cause an exception; instead, infinity is returned.) The following code causes an unhandled divide-by-zero exception, which terminates the application:

using System;

namespace Donis.CSharpBook {
    public class Starter {
        public static void Main() {
            int var1 = 5, var2 = 0;
            var1 /= var2;    // exception occurs
        }
    }
}

Place code that you think is likely to raise an exception in a try block, where it is protected from exceptions. Exceptions raised in the try block are trapped. The stack then is walked by the CLR to locate an appropriate exception handler. Code not within the scope of a try block is unprotected from exceptions. In this circumstance, the exception eventually evolves into an unhandled exception. As demonstrated in the previous code, an unhandled exception is apt to abort an application.

In the following code, the divide-by-zero exception is caught in a try block. Trapping, catching, and handling an exception are separate tasks. The catch statement consists of a catch filter and a statement block. The DivideByZeroException filter catches the divide-by-zero exception. The catch statement block is where the exception is handled. In this example, the stack trace is displayed. The location of the infraction should be included in the stack trace, which is useful. After the exception is handled, the execution then continues at the first statement after the catch statement block:

using System;

namespace Donis.CSharpBook {
    public class Starter {
        public static void Main() {
            try {
                int var1 = 5, var2 = 0;
                var1 /= var2;    // exception occurs
            }
            catch(DivideByZeroException except) {
                Console.WriteLine("Exception " + except.StackTrace);
            }
        }
    }
}
..................Content has been hidden....................

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