Using Formal Error Handling (Ready,

for RuBoard

Using Formal Error Handling (Ready, "Catch"!)

An exception occurs when an error condition is encountered . Whether you want to handle it depends on the requirements that you are trying to meet. Certain error conditions might be tolerable but others are not. Typical error conditions would be things like database connection denied or lost, unsuccessful update operations, or even divide-by-zero errors. .NET refers to these conditions as "exceptions" and provides several features to the developer to devise the appropriate response (or lack of response). The primary error-handling constructs we will be using are either the Try/Catch/Finally structure or the On Error construct. But, before discussing these constructs, let's look at an overall error-handling strategy.

Design Considerations

When designing an application, the developer needs to consider the possible exceptions and to design an overall strategy on how to handle them. If this analysis and design are postponed until the end of the development cycle, a steeper price will be paid in code reconstruction and testing delays. Among the issues that the developer needs to consider are which errors to report and how to report them to the different audiences of the application. For instance, a user needs to get feedback about whether an operation was successful, and if not successful, what the next step might be. If the condition is a serious error, a log might need to be generated for the system administrator that describes the issue along with where and when it happened so that the problem can be traced and then possibly fixed by other means. Errors such as database corruption and other data resource integrity issues are good candidates for formal error handling as well. If the application doesn't handle an exception, it bubbles up the stack until the application crashes and system messages are displayed to the user. In most scenarios, this is not a desirable outcome.

If an application handles every possible error scenario, the application is said to be "robust." However, being robust is just a relative term ”most applications and operating systems are more or less robust. But, having too much error handling comes at a price in terms of extra code that needs to be written, tested , and later maintained .

The moral of the story is that the application developer should consider the general processing requirements from the beginning so that he or she can strike a balance between costs and benefits for the specific application. So, on the one hand, an Internet stock brokerage application needs to be extremely robust; it must account for all different types of error conditions, handle them nicely , and provide automatic recovery. An in-house small intranet application can probably get by with general error trapping and a request for the user to retry things, or even settle for a system-generated error (unhandled error).

How the Exception Mechanism Works

At runtime, applications use a stack of method calls. Normally, at the bottom of the stack is the Main method, which then calls other methods, which then call other methods . The system uses the program stack to keep track of where to return after a method finishes. A stack might look like this:

 HowTo.ADONET24.Samples.TryCatch.Run()      HowTo.ADONET24.Samples.TryCatch.Main() 

When an error occurs, the system checks whether the code was executed within a Try/Catch/Finally structure or an On Error handler has been enabled. Control is changed to the appropriate place and the current stack location is part of the error information.

If an exception occurs, and the developer didn't include a Try/Block/Finally structure or enable an On Error handler, the system stops executing at the current stack level. The system then removes the current level from the stack, and transfers controls to the previous stack level, where the system continues to move back up the stack. The system repeats the process of stopping, removing, and transferring to the previous stack level, until a Try/Catch/Finally structure is found or until the last level is reached, at which time the system aborts execution. This is called crashing an application, and should be avoided. In other words, catch it somewhere before it hits the end user.

As an alternative to the Try/Catch/Finally structure, .NET provides an On Error handler structure as well. Either structure can be used for error handling.

The Try/Catch/Finally Structure

The .NET Common Language Runtime (or CLR) provides the Try/Catch/Finally structure from which areas of code that encounter exceptions can be handled. When an exception does occur to code that is part of the Try block, the .NET CLR stops the normal logic flow and transfers control from the Try block to the Catch block where the developer can take a course of action (such as notifying the user or some recovery action). Regardless of whether an exception occurred, the Finally block will be executed (if one is provided).

If errors occur that the developer has not handled, the VS .NET application simply provides its normal error messages to the user. This isn't always handled very gracefully, so we encourage you to handle the errors and provide the appropriate correction or recovery logic.

The Try/Catch/Finally Statement

The Try block contains the code where an error can occur. The Catch block contains the code to handle the error when it occurs. When an error does occur, program control is passed to the appropriate catch statement for evaluation. The exception argument is an instance of the Exception class and contains information about the error, the error number, and the error message. The When expression can be used when looking for a specific error and should evaluate to true. After the normal execution or after the Catch block, the system executes the Finally block, which is typically used for clean-up operations. The following pseudocode shows the structure of the Try/Catch/Finally block:

  Try  [ try statements ] [  Catch  [ exception [  As  type ] [  When  expression]    [ catch statements ]  ] [ Exit Try ] [ additional Catch blocks, if desired ... ] [  Finally  [ Finally statements ] ]  End Try  

The short piece of code in Listing 13.1 illustrates the Try/Catch/Finally error-handling structure. The program has two sections of code. The first section will use the Try/Catch/Finally structure and handle a simple error (divide by zero), and the second code section will create the same error but without any type of error-handling structure. Note the differences when you execute the code.

Listing 13.1 The Try/Catch/Finally Structure (13TryCatch.vb)
 Imports System namespace HowTo.ADONET24.Samples public class TryCatch   public shared sub Main()     Dim myTryCatch as TryCatch     myTryCatch = new TryCatch()     myTryCatch.Run()   end sub   public sub Run()     Dim a As Integer = 100     Dim b As Integer = 0     try       Console.WriteLine("*** TRY BLOCK - WE WILL DO A DIVISION BY ZERO ***")       a /= b    ' Divide by zero... arithmetic error     Catch e As Exception When b = 0       Console.WriteLine("*** CATCH BLOCK - ERROR - WE         WILL HANDLE THIS OURSELVES ***")       Console.WriteLine(e.ToString())     Finally       Console.WriteLine("*** FINALLY BLOCK - ALWAYS EXECUTED ***")     end try     Console.WriteLine()     Console.WriteLine("*** NOW, DO A DIVISION BY ZERO        AGAIN WITHOUT HANDLING IT ***")     a /= b    ' Divide by zero... arithmetic error   end sub end class 

Let's compile and execute this to show the logic flow of this Try/Catch/Finally structure as follows :

 C:\ADOSAMPLES>  vbc.exe 13TryCatch.vb  /r:System.dll 

You should see the following .NET VB compiler messages:

 Microsoft (R) Visual Basic .NET Compiler version 7.00.9447 for Microsoft (R) .NET Framework version 1.00.3617 Copyright (C) Microsoft Corporation 1987-2001. All rights reserved. 

This message is followed by the DOS command prompt again (if it is a successful compile). Otherwise, you will be getting compile errors of one kind or another. Now, to execute, just specify the sample name at the DOS command prompt and press Enter.

 C:\ADOSAMPLES>  13TryCatch.exe  <press enter> *** TRY BLOCK - WE WILL DO A DIVISION BY ZERO *** *** CATCH BLOCK - ERROR - WE WILL HANDLE THIS OURSELVES *** System.OverflowException: Arithmetic operation resulted in an overflow.    at HowTo.ADONET24.Samples.TryCatch.Run() *** FINALLY BLOCK - ALWAYS EXECUTED *** *** NOW, DO A DIVISION BY ZERO AGAIN WITHOUT HANDLING IT *** Unhandled Exception: System.OverflowException: Arithmetic operation resulted in an overflow.    at HowTo.ADONET24.Samples.TryCatch.Run()    at HowTo.ADONET24.Samples.TryCatch.Main() 

The On Error Construct

As an alternative to Try/Catch/Finally , you can use the On Error construct. This approach enables an error-handling routine and specifies the location of the routine within a procedure. The On Error routine takes the following form:

  On Error  {  GoTo  [ line    0    -1  ]  Resume Next  } 

You first have to enable the On Error handler before it can be utilized. The GoTo provides the branch to an enabled handler. The Resume Next directs the control of flow to go to the statement immediately following the statement where the error occurred, and execution continues from that point. The code example in Listing 13.2 illustrates the On Error construct.

Listing 13.2 The On Error Construct (13OnError.vb)
 Imports System Imports Microsoft.VisualBasic namespace HowTo.ADONET24.Samples public class OnErrorT   public shared sub Main()     Dim myOnErrorT as OnErrorT     myOnErrorT = new OnErrorT()     myOnErrorT.Run() uh,mily  end sub   public sub Run()     Dim a As Integer = 100     Dim b As Integer = 0     Console.WriteLine(">>> Enable the error handler <<<")     On Error Goto EHandler     Err.Clear     Console.WriteLine("*** WE WILL DO A DIVISION BY ZERO ***")     a /= b    ' Divide by zero... arithmetic error     Console.WriteLine("*** Recovered from error, ending ***")     Exit Sub     EHandler:             Console.WriteLine("     *** ERROR HANDLER ***")             Select Case Err.Number               Case 6                  Console.Writeline("     *** you have divided by zero ***")               Case Else                  Console.Writeline("     *** other error encountered ***")             End Select             Resume Next   end sub end class end namespace 

Let's compile and execute this one as well to show the logic flow of the On Error construct:

 C:\ADOSAMPLES>  vbc.exe 13OnError.vb  /r:System.dll 

This is followed by the DOS command prompt again (if it is a successful compile). Otherwise, you will be getting compile errors of one kind or another. Now, to execute, just specify the sample name at the DOS command prompt and press Enter.

 C:\ADOSAMPLES>  13OnError.exe  <press enter> >>> Enable the error handler <<< *** WE WILL DO A DIVISION BY ZERO ***      *** ERROR HANDLER ***      *** you have divided by zero *** *** Recovered from error, ending *** 

Throw It If You Know It

You can also utilize the Throw statement in either Try/Catch/Finally or On Error constructs. The Throw statement raises an exception that is represented by an instance of a type derived from the System.Exception class.

Here's a Throw statement with the On Error construct:

 On Error Goto Ehandler Throw New DivideByZeroException() Ehandler:     If (typeof Err.GetException() Is DivideByZeroException) Then        Console.writeline("using throw exception setting")     End If 

Or, with the Try/Catch/Finally construct:

 Try    a /= b    ' Divide by zero... arithmetic error Catch e As Exception When b = 0    Throw New DivideByZeroException() 
for RuBoard


Sams Teach Yourself ADO. NET in 24 Hours
Sams Teach Yourself ADO.NET in 24 Hours
ISBN: 0672323834
EAN: 2147483647
Year: 2002
Pages: 237

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