Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
(ebook) Visual Studio .NET Mastering Visual Basic.pdf
Скачиваний:
120
Добавлен:
17.08.2013
Размер:
15.38 Mб
Скачать

796 Chapter 17 ERROR HANDLING AND DEBUGGING

highlight a row in a grid that doesn’t exist). In this case, fixing the logic error would automatically fix the runtime error.

Exceptions and Structured Exception Handling

A runtime error in VB.NET generates an exception. An exception is a response to the error condition that the program just generated. Figure 17.6 is an example of an exception message. This is the dialog that appears when you are running your program in the IDE. If the same error were to be encountered by a user running your program, the dialog would look slightly different, as seen in Figure 17.7.

Figure 17.6

Design-time error message

Figure 17.7

Runtime error message

Note that this dialog gives the user the opportunity to continue the program. In some rare cases, this might be desirable, but in most cases you probably would not want your users attempting to continue after a program exception has occurred. Think about it—your program has just encountered some form of data that it cannot handle correctly, and now it’s asking the user if it should attempt to ignore that bad data and continue. It is difficult to predict what type of further problems might result as the program continues on and attempts to handle the bad data. Most likely, further exceptions will be generated as the subsequent lines of code attempt to deal with the same unexpected data.

If we don’t want our users handling an exception that the program generates, then we’ll simply have to handle it ourselves. The Visual Basic .NET error-handling model allows us to do just that. An error handler is a section of VB.NET code that allows you to detect exceptions and perform the necessary steps to recover from them. What follows are some exception-handling code examples.

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

EXCEPTIONS AND STRUCTURED EXCEPTION HANDLING 797

Studying an Exception

The exception dialogs shown in Figures 17.6 and 17.7 were generated by the VB.NET code shown in Listing 17.1.

Listing 17.1: An Unhandled Exception

Private Sub Button2_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles Button2.Click Dim s As String

s = “answer”

Button2.Text = s.Substring(10, 1) End Sub

This code is attempting to display the eleventh character in the string “answer”. Seeing as the word “answer” contains only six characters, you can imagine how an exception might be generated. Let’s examine at the exact phrasing of the exception to learn as much as possible about this particular error.

An unhandled exception of type ‘System.ArgumentOutOfRangeException’ occurred in mscorlib.dll

Additional information: Index and length must refer to a location within the string.

Note This seems almost too trivial to mention, but always thoroughly read the exceptions that your program generates. Their purpose is to give you a brief description of the condition that caused the error, which of course is necessary to know before you can figure out how to handle it.

The first thing to notice is the fact that this message refers to this runtime error as an unhandled exception. This means that the line of code that generated this error is not contained within an exception-handling block.

The second interesting piece of information is that this exception is of type System.ArgumentOutOfRangeException, whatever that means. What’s important to note is that the different types of errors can be classified in groups. This is important when we you realize that the .NET Framework exception-handling mechanism follows the same object-oriented design principles that the rest of the Framework follows. An exception creates an instance of an object, and that object is a descendent of class Exception.

The error message above is telling us that the exception object instance generated is of class (type) System.ArgumentOutOfRangeException, which is a descendent of class Exception.

The “additional information” block gives us some specific notes on the nature of the error. It tells us that the index and length parameters of the Substring method must both lie within the boundaries of the string. In our case, we attempted to retrieve the eleventh character of a six-character string, clearly outside the boundary.

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

798 Chapter 17 ERROR HANDLING AND DEBUGGING

Getting a Handle on this Exception

Listing 17.2 is the same defective code statement as Listing 17.1, but with a simple exception handler wrapped around it.

Listing 17.2: Handling an Exception, Version 1

Private Sub Button2_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles Button2.Click Dim s As String

s = “answer” Try

Button2.Text = s.Substring(10, 1) Catch

Button2.Text = “error” End Try

End Sub

This code attempts to do the same thing as the code above, but this time the faulty Substring statement is wrapped around a Try…Catch…End Try block. This block is a basic exception handler. If any of the code after the Try statement generates an exception, then program control automatically jumps to the code after the Catch statement. If no exceptions are generated in the code under the Try statement, then the Catch block is skipped. When this code is run, the System.ArgumentOutOfRangeException is generated, but now the code does not terminate with a message box. Instead, the text property of Button2 is set to the word “error”, and the program continues along.

Listing 17.3 handles the same error in a slightly different way.

Listing 17.3: Handling an Exception, Version 2

Private Sub Button2_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles Button2.Click Dim s As String

s = “answer” Try

Button2.Text = s.Substring(10, 1) Catch oEX As Exception

Call MsgBox(oEX.Message) End Try

End Sub

In this example, the exception generates an instance of the Exception class and places that instance in a variable named oEX. Having the exception instance variable is useful because it can give you the text of the exception, which we display in a message box here. Of course, displaying the exception message in a message box is pretty much the same thing that your program does when an unhandled

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

EXCEPTIONS AND STRUCTURED EXCEPTION HANDLING 799

exception is generated, so it’s doubtful that you would do this in your own program. However, you could log the exception text to the event log or a custom error file.

Note that the exception handlers above do not differentiate between types of errors. If any exception is generated within the Try block, then the Catch block is executed. You can also write exception handlers that handle different classes of errors, as seen in Listing 17.4.

Listing 17.4: Handling an Exception, Version 3

Private Sub Button3_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles Button3.Click

Try

Button3.Text = lbStates.SelectedItem.ToString

Catch oEX As System.NullReferenceException

Call MsgBox(“Please select an item first”)

Catch oEX As Exception

Call MsgBox(“Some other error: “ & oEX.Message)

End Try

End Sub

This code attempts to take the selected item in a ListBox named lbStates and display it as the caption of a button. If no item is selected in the ListBox, then a System.NullReferenceException will be generated, and we use that information to tell the user to select an item in the ListBox. If any other type of exception is generated, then this code displays the text of that error message.

Note that, in the list of exceptions in Listing 17.4, the more specific exception handler comes first and the more general exception handler comes last. This is how you’ll want to code all of your multiple Catch exception handlers so that they are handled in the correct order. If you put your more general Catch handlers first, then they will execute first and override the more specific handlers.

Also note that the variable oEX is reused in each of the exception blocks. This is possible because the Catch statement actually serves as a declaration of that variable (note that I didn’t have to Dim the oEX variable anywhere) and that the oEX variable has a local scope only within the Catch block.

Note that because the Exception instance is declared in each Catch block, it has scope only within that block. The code in Listing 17.5 is illegal for scoping reasons.

Listing 17.5: Handling an Exception, Version 4 (Illegal)

Private Sub Button3_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles Button3.Click

Try

Button3.Text = lbStates.SelectedItem.ToString

Catch oEX As System.NullReferenceException

Call MsgBox(“please select an item first”)

Catch oEX As Exception

Call MsgBox(“some other error”)

End Try

MsgBox(oEX.message)

End Sub

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com