Exception Handling Fundamentals


C# exception handling is managed via four keywords: try, catch, throw, and finally. They form an interrelated subsystem in which the use of one implies the use of another. Throughout the course of this chapter, each keyword is examined in detail. However, it is useful at the outset to have a general understanding of the role each plays in exception handling. Briefly, here is how they work.

Program statements that you want to monitor for exceptions are contained within a try block. If an exception occurs within the try block, it is thrown. Your code can catch this exception using catch and handle it in some rational manner. System-generated exceptions are automatically thrown by the C# runtime system. To manually throw an exception, use the keyword throw. Any code that absolutely must be executed upon exiting from a try block is put in a finally block.

Using try and catch

At the core of exception handling are try and catch. These keywords work together; you can’t have a catch without a try. Here is the general form of the try/catch exception handling blocks:

 try {    // block of code to monitor for errors } catch (ExcepType1 exOb) {    // handler for ExcepType1 } catch (ExcepType2 exOb) {    // handler for ExcepType2 } . . .

Here, ExcepType is the type of exception that has occurred. When an exception is thrown, it is caught by its corresponding catch statement, which then processes the exception. As the general form shows, there can be more than one catch statement associated with a try. The type of the exception determines which catch statement is executed. That is, if the exception type specified by a catch statement matches that of the exception, then that catch statement is executed (and all others are bypassed). When an exception is caught, exOb will receive its value.

Actually, specifying exOb is optional. If the exception handler does not need access to the exception object (as is often the case), there is no need to specify exOb. For this reason, many of the examples in this chapter will not specify exOb.

Here is an important point: If no exception is thrown, then a try block ends normally, and all of its catch statements are bypassed. Execution resumes with the first statement following the last catch. Thus, catch statements are executed only if an exception is thrown.

A Simple Exception Example

Here is a simple example that illustrates how to watch for and catch an exception. As you know, it is an error to attempt to index an array beyond its boundaries. When this occurs, the C# runtime system throws an IndexOutOfRangeException, which is a standard exception defined by C#. The following program purposely generates such an exception and then catches it:

 // Demonstrate exception handling. using System; class ExcDemo1 {   public static void Main() {     int[] nums = new int[4];     try {       Console.WriteLine("Before exception is generated.");       // Generate an index out-of-bounds exception.       for(int i=0; i < 10; i++) {         nums[i] = i;         Console.WriteLine("nums[{0}]: {1}", i, nums[i]);       }       Console.WriteLine("this won't be displayed");     }     catch (IndexOutOfRangeException) {       // catch the exception       Console.WriteLine("Index out-of-bounds!");     }     Console.WriteLine("After catch statement.");   } }

This program displays the following output:

 Before exception is generated. nums[0]: 0 nums[1]: 1 nums[2]: 2 nums[3]: 3 Index out-of-bounds! After catch statement.

Notice that nums is an int array of four elements. However, the for loop tries to index nums from 0 to 9, which causes an IndexOutOfRangeException to occur when an index value of 4 is tried.

Although quite short, the preceding program illustrates several key points about exception handling. First, the code that you want to monitor for errors is contained within a try block. Second, when an exception occurs (in this case, because of the attempt to index nums beyond its bounds inside the for loop), the exception is thrown out of the try block and caught by the catch statement. At this point, control passes to the catch, and the try block is terminated. Therefore, catch is not called. Rather, program execution is transferred to it. Thus, the WriteLine( ) statement following the out-of-bounds index will never execute. After the catch statement executes, program control continues with the statements following the catch. It is the job of your exception handler to remedy the problem that caused the exception so that program execution can continue normally.

Notice that no parameter is specified in the catch clause. As mentioned, a parameter is needed only when access to the exception object is required. In some cases, the value of the exception object can be used by the exception handler to obtain additional information about the error, but in many cases it is sufficient to simply know that an exception occurred. Thus, it is not unusual for the catch parameter to be absent in the exception handler, as is the case in the preceding program.

As explained, if no exception is thrown by a try block, no catch statements will be executed, and program control resumes after the catch statement. To confirm this, in the preceding program, change the for loop from

 for(int i=0; i < 10; i++) {

to

 for(int i=0; i < nums.Length; i++) {

Now, the loop does not overrun nums’ boundary. Thus, no exception is generated, and the catch block is not executed.

A Second Exception Example

It is important to understand that all code executed within a try block is monitored for exceptions. This includes exceptions that might be generated by a method called from within the try block. An exception thrown by a method called from within a try block can be caught by that try block, assuming, of course, that the method itself did not catch the exception.

For example, consider the following program. Main( ) establishes a try block from which the method genException( ) is called. Inside genException( ), an IndexOutOfRangeException is generated. This exception is not caught by genException( ). However, since genException( ) was called from within a try block in Main( ), the exception is caught by the catch statement associated with that try.

 /* An exception can be generated by one    method and caught by another. */ using System; class ExcTest {   // Generate an exception.   public static void genException() {     int[] nums = new int[4];     Console.WriteLine("Before exception is generated.");     // Generate an index out-of-bounds exception.     for(int i=0; i < 10; i++) {       nums[i] = i;       Console.WriteLine("nums[{0}]: {1}", i, nums[i]);     }     Console.WriteLine("this won't be displayed");   } } class ExcDemo2 {   public static void Main() {     try {       ExcTest.genException();     }     catch (IndexOutOfRangeException) {       // catch the exception       Console.WriteLine("Index out-of-bounds!");     }     Console.WriteLine("After catch statement.");   } }

This program produces the following output, which is the same as that produced by the first version of the program shown earlier:

 Before exception is generated. nums[0]: 0 nums[1]: 1 nums[2]: 2 nums[3]: 3 Index out-of-bounds! After catch statement.

As explained, since genException( ) is called from within a try block, the exception that it generates (and does not catch) is caught by the catch in Main( ). Understand, however, that if genException( ) had caught the exception, then it would never have been passed back to Main( ).




C# 2.0(c) The Complete Reference
C# 2.0: The Complete Reference (Complete Reference Series)
ISBN: 0072262095
EAN: 2147483647
Year: 2006
Pages: 300

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net