Section 12.4. Example: Handling DivideByZeroExceptions and FormatExceptions


12.4. Example: Handling DivideByZeroExceptions and FormatExceptions

Let us consider a simple example of exception handling. The application in Fig. 12.2 uses exception handling to process any DivideByZeroExceptions and FormatExceptions that might arise. The application displays two TextBoxes in which the user can type integers. When the user presses Click To Divide, the program invokes event handler btnDivide_Click (lines 633), which obtains the user's input, converts the input values to type Integer and divides the first number (numerator) by the second number (denominator). Assuming that the user provides integers as input and does not specify 0 as the denominator, btnDivide_Click displays the division result in lblOutput. However, if the user inputs a noninteger value or supplies 0 as the denominator, an exception occurs. This program demonstrates how to catch and handle (i.e., deal with) such exceptionsin this case, displaying an error message and allowing the user to enter another set of values.

Figure 12.2. FormatException and DivideByZeroException exception handlers.

  1  ' Fig. 12.2: DivideByZeroTest.vb  2  ' Exception handlers for FormatException and DivideByZeroException.  3  Public Class frmDivideByZeroTest  4     ' obtain 2 integers from the user  5     ' and divide numerator by denominator  6     Private Sub btnDivide_Click(ByVal sender As System.Object, _  7        ByVal e As System.EventArgs) Handles btnDivide.Click  8  9        lblOutput.Text = "" ' clear Label lblOutput 10 11        ' retrieve user input and calculate quotient                         12        Try                                                                  13           ' Convert.ToInt32 generates FormatException                       14           ' if argument is not an integer                                   15           Dim numerator As Integer = Convert.ToInt32(txtNumerator.Text)     16           Dim denominator As Integer = Convert.ToInt32(txtDenominator.Text) 17         18           ' division generates DivideByZeroException                        19           ' if denominator is 0                                             20           Dim result As Integer = numerator \ denominator                   21         22           ' display result in lblOutput                                     23           lblOutput.Text = result.ToString()                                24        Catch formatExceptionParameter As FormatException                    25           MessageBox.Show("You must enter two integers.", _                 26              "Invalid Number Format", MessageBoxButtons.OK, _              27              MessageBoxIcon.Error)                                          28        Catch divideByZeroExceptionParameter As DivideByZeroException        29           MessageBox.Show(divideByZeroExceptionParameter.Message, _         30              "Attempted to Divide by Zero", MessageBoxButtons.OK, _         31              MessageBoxIcon.Error )                                         32        End Try                                                              33     End Sub ' btnDivide_Click 34  End Class ' frmDivideByZeroTest 

(a)

(b)

(c)

(d)

(e)

Before we discuss the program's details in Sections 12.4.112.4.5, let's consider the sample output windows in Fig. 12.2. The window in Fig. 12.2(a) shows a successful calculation, in which the user enters the numerator 100 and the denominator 7. Note that the result (14) is an Integer, because integer division always yields an Integer result. The next two windows, Fig. 12.2(b and c), demonstrate the result of an attempt to divide by zero. In integer arithmetic, the CLR tests for division by zero and, if the denominator is zero, generates a DivideByZeroException. The program detects the exception and displays the error message dialog in Fig. 12.2(c) indicating the attempt to divide by zero. The last two output windows, Fig. 12.2(d) and Fig. 12.2(e), depict the result of inputting a non-Integer valuein this case, the user enters "hello" in the second TextBox, as shown in Fig. 12.2(d). When the user clicks Click To Divide, the program attempts to convert the input Strings into Integer values using method Convert.ToInt32 (lines 1516). If an argument passed to Convert.ToInt32 cannot be converted to an Integer value, the method throws a FormatException. The program catches the exception and displays the error message dialog in Fig. 12.2(e) indicating that the user must enter two Integers.

12.4.1. Enclosing Code in a try Block

Now we consider the user interactions and flow of control that yield the results shown in the sample output windows. The user inputs values into the TextBoxes that represent the numerator and denominator, then presses Click To Divide. At this point, the program invokes method btnDivide_Click. Line 9 assigns the empty string to lblOutput to clear any prior result in preparation for a new calculation. Lines 1223 define a try block enclosing the code that might throw exceptions, as well as the code that is skipped when an exception occurs. For example, the program should not display a new result in lblOutput (line 23) unless the calculation in line 20 completes successfully.

The two statements that read the Integers from the TextBoxes (lines 1516) call method Convert.ToInt32 to convert Strings to Integer values. This method throws a FormatException if it cannot convert its String argument to an Integer. If lines 1516 convert the values properly (i.e., no exceptions occur), then line 20 divides the numerator by the denominator. If denominator is 0, line 20 causes the CLR to throw a DivideByZeroException. If line 20 does not cause an exception to be thrown, then the result is assigned to variable result and line 23 displays the result of the division.

12.4.2. Catching Exceptions

Exception-handling code appears in a Catch block. In general, when an exception occurs in a try block, a corresponding Catch block catches the exception and handles it. The try block in this example is followed by two Catch blocksone that handles a FormatException (lines 2427) and one that handles a DivideByZeroException (lines 2831). A Catch block specifies an exception parameter representing the exception that the Catch block can handle. The Catch block can use the parameter's identifier (which is chosen by the programmer) to interact with a caught exception object. The type of the Catch's parameter is the type of the exception that the Catch block handles. Optionally, you can include a Catch block that does not specify an exception type or an identifiersuch a Catch block catches all exception types. At least one Catch block or a Finally block (discussed in Section 12.6) must immediately follow a try block.

In Fig. 12.2, the first Catch block (lines 2327) catches FormatExceptions (thrown by method Convert.ToInt32), and the second Catch block (lines 2831) catches DivideByZeroExceptions (thrown by the CLR). If an exception occurs, the program executes only the first matching Catch block. Both exception handlers in this example display an error message dialog. After either Catch block terminates, program control continues with the first statement after the last Catch block (the end of the method, in this example). We will soon take a deeper look at how this flow of control works in exception handling.

12.4.3. Uncaught Exceptions

An uncaught exception is an exception for which there is no matching Catch block. You saw the results of uncaught exceptions in the second and third outputs of Fig. 12.1. Recall that when exceptions occur in that example, the application terminates early (after displaying the exception's stack trace). The result of an uncaught exception depends on how you execute the programFig. 12.1 demonstrated the results of an uncaught exception when an application is executed in a Command Prompt. If you run the application from Visual Studio with debugging and the runtime environment detects an uncaught exception, the application pauses, and a window called the Exception Assistant appears indicating where the exception occurred, the type of the exception and links to helpful information on handling the exception. Figure 12.3 shows the Exception Assistant that is displayed if the user attempts to divide by zero in the application of Fig. 12.1.

Figure 12.3. Exception Assistant.


12.4.4. Termination Model of Exception Handling

When a method called in a program or the CLR detects a problem, the method or the CLR throws an exception. Recall that the point in the program at which an exception occurs is called the throw pointthis is an important location for debugging purposes (as we demonstrate in Section 12.7). If an exception occurs in a TRy block (such as a FormatException being thrown as a result of the code in line 16 in Fig. 12.2), the TRy block terminates immediately, and program control transfers to the first of the following Catch blocks in which the exception parameter's type matches the type of the thrown exception. In Fig. 12.2, the first Catch block catches FormatExceptions (which occur if input of an invalid type is entered); the second Catch block catches DivideByZeroException (which occur if an attempt is made to divide by zero). After the exception is handled, program control does not return to the throw point because the try block has expired (which also causes any of its local variables to go out of scope). Rather, control resumes after the last Catch block. This is known as the termination model of exception handling. [Note: Some languages use the resumption model of exception handling, in which after an exception is handled, control resumes just after the throw point.]

Common Programming Error 12.1

Logic errors can occur if you assume that after an exception is handled, control will return to the first statement after the throw point.


If no exceptions occur in the try block, the program of Fig. 12.2 successfully completes the TRy block by ignoring the Catch blocks in lines 2427 and 2831, and passing over line 32. Then the program executes the first statement following the TRy and Catch blocks. In this example, the program reaches the end of event handler btnDivide_Click (line 33), so the method terminates, and the program awaits the next user interaction.

The try block and its corresponding Catch and Finally blocks together form a try statement. It is important not to confuse the terms "try block" and "TRy statement"the term "try block" refers to the block of code following the keyword TRy (but before any Catch or Finally blocks), while the term "try statement" includes all the code from the opening try keyword to the closing End Try. This includes the try block, as well as any associated Catch blocks and Finally block, if there is one.

As with any other block of code, when a try block terminates, local variables defined in the block go out of scope. If a try block terminates due to an exception, the CLR searches for the first Catch block that can process the type of exception that occurred. The CLR locates the matching Catch by comparing the type of the thrown exception to each Catch's parameter type. A match occurs if the types are identical or if the thrown exception's type is a derived class of the Catch's parameter type. Once an exception is matched to a Catch block, the code in that block executes and the other Catch blocks in the try statement are ignored.

12.4.5. Flow of Control When Exceptions Occur

In the sample output of Fig. 12.2(b), the user inputs 0 as the denominator. When the division in line 20 executes, a DivideByZeroException occurs. When the exception occurs, the try block expires (terminates). Next, the CLR attempts to locate a matching Catch block. In this case, the first Catch block does not matchthe exception type in the Catch-handler declaration is not the same as the type of the thrown exception, and FormatException is not a base class of DivideByZeroException. Therefore the program continues to search for a matching Catch block, which it finds in line 28. Line 29 displays the value of property Message of class Exception, which contains the error message. Note that our program never "sets" this error message attribute. This is done by the CLR when it creates the exception object.

In the sample output of Fig. 12.2(d), the user inputs hello as the denominator. When line 16 executes, Convert.ToInt32 cannot convert this String to an Integer, so Convert.ToInt32 throws a FormatException object to indicate that the method was unable to convert the String to an Integer. Once again, the try block terminates, and the program attempts to locate a matching Catch block. A match occurs with the Catch block in line 24, so the exception handler executes and the program ignores all other exception handlers following the try block.

Common Programming Error 12.2

Specifying a comma-separated list of parameters in a Catch block is a syntax error. A Catch block can have at most one parameter.




Visual BasicR 2005 for Programmers. DeitelR Developer Series
Visual Basic 2005 for Programmers (2nd Edition)
ISBN: 013225140X
EAN: 2147483647
Year: 2004
Pages: 435

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