Export (0) Print
Expand All
Around the World with Visual Basic
Asynchronous Method Execution Using Delegates
Building a Progress Bar that Doesn't Progress
Calling All Operators
Create a Graphical Editor Using RichTextBox and GDI+
Creating A Breadcrumb Control
Creating a Five-Star Rating Control
Creating and Managing Secondary Threads
Data Binding Radio Buttons to a List
Deploying Assemblies
Designing With Custom Attributes
Digital Grandma
Doing Async the Easy Way
Extracting Data from .NET Assemblies
Implementing Callbacks with a Multicast Delegate
Naming and Building Assemblies in Visual Basic .NET
Programming Events of the Framework Class Libraries
Programming I/O with Streams in Visual Basic .NET
Reflection in Visual Basic .NET
Remembering User Information in Visual Basic .NET
Advanced Basics: Revisiting Operator Overloading
Scaling Up: The Very Busy Background Compiler
Synchronizing Multiple Windows Forms
Thread Synchronization
Updating the UI from a Secondary Thread
Using Inheritance in the .NET World
Using the ReaderWriterLock Class
Visual Basic: Simplify Common Tasks by Customizing the My Namespace
What's My IP Address?
Windows Forms Controls: Z-order and Copying Collections
Expand Minimize

Introduction to Exception Handling in Visual Basic .NET

Visual Studio .NET 2003
 

Cat Francis
Visual Studio Team
Microsoft Corporation

February 2002

Knowledge rests not upon truth alone, but upon error also. — Carl Jung

Summary: This article provides an overview of structured and unstructured exception handling in Visual Basic .NET. It includes considerations that help you choose the right exception-handling alternative, the approaches involved in each alternative, how to create your own exceptions, and the exception object's properties. A table at the end lists the predefined exception classes and their derived classes. (17 printed pages)

Contents

Introduction
Unstructured Exception Handling
Structured Exception Handling
Conclusions

Introduction

Only perfect programmers create perfect code from the beginning. The rest must address imperfections along the way to developing a successful application.

Luckily for us Microsoft® Visual Basic® .NET offers two ways of handling exceptions. The first, unstructured, follows the exception-handling conventions of earlier versions of Visual Basic. The second, structured, handles exceptions in ways that resemble exception handling in Microsoft® Visual C#™ and Microsoft® Visual C++®.

This article, which is aimed at the beginning Visual Basic developer or at developers who are transitioning from earlier versions of Visual Basic to Visual Basic .NET, provides an overview of structured and unstructured exception handling. It includes considerations that help you choose the right exception-handling alternative, the approaches involved in each alternative, how to create your own exceptions, and the exception object's properties. By the time you are finished, you should understand how and when to incorporate exception handling in your code.

Definitions of Errors and Exceptions

The terms, error and exception, are often used interchangeably. In fact, an error, which is an event that happens during the execution of code, interrupts or disrupts the code's normal flow and creates an exception object. When an error interrupts the flow, the program tries to find an exception handler — a block of code that tells it how to react — that will help it resume the flow. In other words, an error is the event; an exception is the object that the event creates.

Programmers use the phrase "throwing an exception" to mean that the method in question encountered an error and reacted by creating an exception object that contains information about the error and when/where it occurred. Factors that cause errors and subsequent exceptions include user error, resource failures, and failures of programming logic. Such errors are related to how the code undertakes a specific task; they are not related to the purpose of the task.

For the purpose of this article, "exception handling" means interpreting and reacting to the exceptions created by errors.

Structured versus Unstructured — When to Use Which

Structured exception handling is simply that — using a control structure containing exceptions, isolated blocks of code, and filters to create an exception handling mechanism. This allows your code to differentiate between different types of errors and react in accordance with circumstances. In unstructured exception handling, an On Error statement at the beginning of the code handles all exceptions.

Structured exception handling is significantly more versatile, robust, and flexible than unstructured. If possible, use structured exception handling. However, you might use unstructured exception handling under these circumstances:

  • You are upgrading an application written in an earlier version of Visual Basic.
  • You are developing a preliminary or draft version of an application and you don't mind if the program fails to shut down gracefully.
  • You know in advance exactly what will cause the exception.
  • A deadline is pressing and you need to take shortcuts.
  • Code is trivial or so short that you only need to test the branch of code generating the exception.
  • You need to use the Resume Next statement, which is not supported in structured exception handling.

You cannot combine structured and unstructured exception handling in the same function. If you use an On Error statement, you cannot use a Try...Catch statement in the same function.

Regardless of which you choose to handle exceptions within your code, you must take a step back and examine what assumptions that code makes. For example, when your application asks the user to input a telephone number, the following assumptions come into play:

  • The user will input a number rather than characters.
  • The number will have a certain format.
  • The user will not input a null string.
  • The user has a single telephone number.

User input might violate any or all of these assumptions. Robust code requires adequate exception handling, which allows your application to recover gracefully from such a violation.

Unless you can guarantee that a method will never throw an exception under any circumstances, allow for informative exception handling. Exception handling should be meaningful. Beyond stating that something went wrong, messages resulting from exception handling should indicate why and where it went wrong. An uninformative message along the lines of "An error has occurred" only frustrates the user.

Structured Exception Handling

Structured exception handling tests specific pieces of the code and, as exceptions occur, adapts your exception-handling code to the circumstances that caused the exception. It is significantly faster in large applications than unstructured exception handling and allows more flexible response to errors as well as greater application reliability.

The Try...Catch...Finally control structure is fundamental to structured exception handling. It tests a piece of code, filters exceptions created by the execution of that code, and reacts differently based on the type of thrown exception.

The Try...Catch...Finally block

Try...Catch...Finally control structures test a piece of code and direct how the application should handle various categories of error. Each of the structure's three constituent parts plays a specific role in this process.

  • The Try statement provides the code that is being tested for exceptions.
  • Catch clauses identify blocks of code that are associated with specific exceptions. A Catch When block directs the code to execute under specific circumstances. A Catch without a When clause reacts to any exception. Therefore, your code might hold a series of specific Catch...When statements, each reacting to a specific type of exception, followed by a general Catch block that reacts to any exceptions that have not been intercepted by the preceding Catch...When clauses.
  • The Finally statement contains code that executes regardless of whether or not an exception occurs within the Try block. A Finally statement will execute even after an Exit Try or Exit Sub. This code often performs clean-up tasks, such as closing files or clearing buffers.

What a Catch Clause Does

A Catch clause can take three possible forms: Catch, Catch...As, and Catch...When.

A Catch clause with no When keyword allows the associated statement block to handle any exception. Catch...As and Catch...When clauses catch a specific exception and allow the associated statement block to tell the application what to do. Catch...As and Catch...When clauses can also be combined in a single statement, such as Catch ex As Exception When intResult <> 0.

If the exception is a result of resource failure, it should identify the resource and, if possible, provide troubleshooting advice or workaround tips. If the exception is a result of a failure of programming logic, the clause should, in all probability, allow the application to exit as gracefully as possible. If user error has caused the exception, however, the code should allow the user to correct his or her error and proceed.

Catch clauses are checked in the order in which they appear in the code. Therefore, catch clauses should move from the specific to the general as they progress through the sequence of code. Check a type before checking its base type, for example. A catch block handling System.Exception should only appear as a final block after the other possibilities have been exhausted.

Imports System
Try
   varAvailableSeats = varAuditoriumSeats - varNumberOfGuests
   Catch ex As Exception When varAuditoriumSeats = 0
   MsgBox("Auditorium lacks chairs!")
   Exit Sub
   Catch ex As Exception When varAvailableSeats < 0
   MsgBox("There are no more available seats.")
   Exit Sub
   Finally MsgBox("Thank you for your interest in our concert.")
End Try

The Exception Object

The Exception object provides information about any encountered exception. Whenever an exception is thrown, the properties of the Err object are set, and a new instance of the Exception object is created. Examine its properties to determine the code location, type, and cause of the exception.

Following are some useful properties of the Exception object:

  • The HelpLink property can hold an URL that points the user to further information about the exception.
  • The HResult property gets or sets HRESULT, a numerical value assigned to the exception. HRESULT is a 32-bit value that contains three fields: a severity code, a facility code, and an error code. The severity code indicates whether the return value represents information, a warning, or an error. The facility code identifies the area of the system responsible for the exception. The error code is a unique number assigned to represent the error.
  • The InnerException property returns an exception object representing an exception that was already in the process of being handled when the current exception was thrown. The code handling the outer exception may be able to use the information from the inner exception in order to handle the outer expression with greater precision.
  • The Message property holds a string, which is the text message that informs the user of the nature of the error and the best way or ways to address it. During the creation of an exception object, you can provide the string best suited to that particular exception. If none is provided, the default string will be provided and formatted according to the current culture.
  • The Source property gets or sets a string containing the name of the object throwing the exception or the name of the assembly where the exception occurred.
  • The StackTrace property holds a stack trace, which you can use to determine where in the code the error occurred. StackTrace lists all the called methods that preceded the exception and the line numbers in the source where the calls were made.
  • The TargetSite property gets the method name that threw the current exception. If the name is not available and the stack trace is not Nothing, the TargetSite property obtains the method name from the stack trace.

Creating Your Own Exceptions for Structured Exception Handling

There are two defined subclasses of exceptions in the Exception base class: System.Exception and Application.Exception.

System.Exception is the class from which the .NET Framework derives the pre-defined common language runtime exception classes. It is thrown by the common language runtime when nonfatal errors occur. System.Exception does not provide information about the cause of the exception.

Note   For further information about the predefined common language runtime exception classes, see Table 1 at the end of this article, which lists the predefined exception classes, their causes, and their derived classes.

You can create your own application exception classes by inheriting them from the Application.Exception class. Follow the strictures of good coding practice by ending the class name of your exception with the word "Exception" — for example, OutOfMoneyException or TooMuchRainException.

The following example defines an exception class and defines three constructors for it, each of which takes different parameters.

Imports System
Public Class GardenException
   Inherits System.ApplicationException
   Public Sub New()
   End Sub
   ' Creates a Sub New for the exception that allows you to set the
   ' message property when thrown.
   Public Sub New(Message As String)
      MyBase.New(Message)
   End Sub
   ' Creates a Sub New that can be used when you also want to include
   ' the inner exception.
   Public Sub New(Message As String, Inner As Exception)
      MyBase.New(Message)
   End Sub
End Class
Note   When using remoting in combination with user-defined exceptions, you must ensure that the metadata for your user-defined exceptions is available to code executing remotely, including exceptions that occur across application domains.

Samples of Structured Exception Handling

This code example is a simple Try...Catch block that first checks for ArithmeticException and then checks for generic exceptions.

Imports System 

   Sub Main()
      Dim x As Integer = 0
      Try
         Dim y As Integer = 100 / x
      Catch ex As ArithmeticException
         MessageBox.Show(ex.Message)
      Catch ex As Exception
         MsgBox(ex.Message)
      End Try
   End Sub 'Main

This code example is a Try...Catch...Finally block associated with an application that opens a file for examination. Note that the Finally statement gets executed even though Exit Sub appears before it in the code.

Imports System
   Sub OpenMyFile
      Dim thisFile As Object
      Try
         FileOpen(1, thisFile, OpenMode.Input)
      Catch ex As Exception
         MsgBox (ex.Message)
         Exit Sub
      Finally 
         FileClose(1)
      End Try
   End Sub

Unstructured Exception Handling

Unstructured exception handling is implemented using the Err object and three statements: On Error, Resume, and Error. The On Error statement establishes a single exception handler that catches all thrown exceptions; you can subsequently change the handler location, but you can only have one handler at a time. The method keeps track of the most recently thrown exception as well as the most recent exception-handler location. At entry to the method, both the exception and the exception-handler location are set to Nothing.

To generate a run-time error in your code, use the Raise method. Whenever an Exit Sub, Exit Function, Exit Property, Resume or Resume Next statement occurs within an error-handling routine, the Err object's properties are reset to zero or zero-length strings. Using any of these outside an error-handling routine does not reset its properties. If you need to do so, you can use the Clear method to reset the Err object.

The Error Object

The values of the properties of the Err object are determined by the error that just occurred. The following table details the properties and provides a short description of each.

Property Description
Description Text message providing a short description of the error.
HelpContext Integer containing the context ID for a topic in a Help file.
HelpFile String expression containing the fully qualified path to a Help file.
LastDLLError System error code produced by a call to a dynamic-link library (DLL). This is the most recently called DLL before the error happened.
Number Numeric value specifying an error.
Source String expression representing the object or application that generated the error.

The following example shows how to use some of these properties in unstructured error handling:

On Error Resume Next
Err.Clear
Err.Raise(33333)
Err.Description = "You didn't input a number!"
MsgBox(Err.Number)
MsgBox(Err.Description)
Msg = "Press F1 or HELP to see " & Err.HelpFile & " topic for" & _
" the following HelpContext: " & Err.HelpContext
MsgBox(Msg)

The On Error GoTo Statement

The On Error GoTo statement enables a routine for exception handling and specifies the location of that routine within the procedure. Used with a label or line number, it directs the code to a specific exception handling routine. Used with -1, it disables error handling within the procedure. Used with 0, it disables the current exception. If there is no On Error statement and the exception is not handled by any methods in the current call stack, then any run-time error that occurs is fatal: execution stops and an error message is displayed.

This table shows the ways the On Error GoTo Statement may be used.

Statement Accomplishes
On Error GoTo -1 Resets Err object to Nothing, disabling error handling in the routine
On Error GoTo 0 Resets last exception-handler location to Nothing, disabling the exception.
On Error GoTo <labelname> Sets the specified label as the location of the exception handler
On Error Resume Next Establishes the Resume Next behavior as the location of the most recent exception handler

Resume and Resume Next

The Resume statement by itself can return control to the statement that caused the exception. The execution resumes at the same line that initially raised the exception.

By contrast, the Resume Next statement resumes execution after an exception has occurred. It specifies that in the event of an exception, control passes to the statement immediately following the statement in which the exception occurred. Resume Next can be used to allow graceful failures; the statement causing the error fails, but the application continues to execute and allows the user to correct the error and continue. Similarly, Resume <label> passes control to a label specified in its line argument. Make sure that the line label is located in the same procedure as the code calling it, since it cannot span between functions.

Resume must be used exclusively in error handling routines. Outside such routines, it causes an error.

The Error Statement

The Error statement is supported in Visual Basic .NET only for backwards compatibility. In new code, use the Err object's Raise method to generate run-time errors.

Samples of Unstructured Exception Handling:

The following example demonstrates a basic approach to unstructured error handling. When the Sub FlawlessCode encounters an error, execution passes to Whoops, which provides the user with information about the error, specifically what's contained in the Err Object's Description property:

Private Sub FlawlessCode()
   On Error GoTo Whoops
   ' Code doing various things
   ' Don't keep going into the error handling code.
   Return
Whoops:
   ' Provide user with error information.
   MsgBox ("Unexpected Error:" & Err.Description)
   Return
End Sub

The following example demonstrates how to use the Err object to construct an error-message dialog box.

Dim ErrorMessage As String
' Construct an error message if an error occurs.
On Error Resume Next
Err.Raise (13) ' Generate type mismatch error.
' Check to see if an error has occurred. If so, show message.
If Err.Number <> 0 Then
   ErrorMessage = "Error # " & Str(Err.Number) & " was generated by " _
      & Err.Source & vbCrLf & Err.Description
' Display the message as a critical message.
   MsgBox(ErrorMessage, MsgBoxStyle.Critical, "Error")
End If

Conclusions

By now, you should have a good idea of the differences between unstructured and structured exception handling, as well as the advantages of the structured exception handling capabilities of Visual Basic .NET. Generally, structured exception handling will meet your needs, but under a few circumstances you might wish to use the unstructured alternative.

While you should make sure exceptions are handled, don't go overboard in throwing them, which can lead to a performance hit. Try structures are organized, easy to write and follow when reading, generate efficient code and should be used any time you have code in which you anticipate the possibility of one or more exceptions. This approach is so enticing, though, that the temptation occurs to use exceptions to control logic flow under normal conditions — for example, instead of an If or Select statement. Handling exceptions is efficient; throwing them should be reserved for genuine exception conditions.

If you wish to investigate exception handling in greater detail, the following three topics are good starting points:

Throwing Exceptions From Components

Best Practices for Handling Exceptions

Error Handling in Duwamish 7.0

The following Table lists the pre-defined exception classes, their causes, and their derived classes.

Table 1

Exception Class Thrown when Derived Classes
AppDomainUnloadedException Attempt made to access an unloaded application domain None
ArgumentException One or more of the arguments provided to a method is not valid ArgumentNullException

ArgumentOutOfRangeException

ComponentModel.InvalidEnum
ArgumentException

DuplicateWaitObjectException

ArithmeticException Errors occur in an arithmetic, casting, or conversion operation DivideByZeroException

NotFiniteNumberException

OverflowException

ArrayTypeMismatchException Attempt made to store an element of the wrong type within an array None
BadImageFormatException File image of a DLL or executable program is invalid None
CannotUnloadAppDomainException Attempt to unload an application domain failed None
ComponentModel.Design.Serialization.
CodeDomSerializerException
Line number information is available for a serialization error None
ComponentModel.LicenseException A component cannot be granted a license None
ComponentModel.WarningException An exception is handled as a warning instead of an error None
Configuration.ConfigurationException An error occurs in a configuration setting None
Configuration.Install.InstallException An error occurs during the commit, rollback, or uninstall phase of an installation None
ContextMarshalException Attempt to marshal an object across a context boundary fails None
Data.DataException Errors are generated using ADO.NET components Data.ConstraintException

Data.DeletedRowInaccessibleException

Data.DuplicateNameException

Data.InRowChangingEventException

Data.InvalidConstraintException

Data.InvalidExpressionException

Data.MissingPrimaryKeyException

Data.NoNullAlllowedException

Data.ReadOnlyException

Data.RowNotInTableException

Data.StringTypingException

Data.TypedDataSetGeneratorException

Data.VersionNotFoundException

Data.DBConcurrencyException During the update operation, the DataAdapter determines that the number of affected rows is equal to zero None
Data.SqlClient.SqlException SQL Server returns a warning or error None
Data.SqlTypes.SqlTypeException Base exception class for Data.SqlTypes Data.SqlTypes.SqlNullValueException

Data.SqlTypes.SqlTruncateException

Drawing.Printing.InvalidPrinterException Attempt made to access a printer using invalid printer settings None
EnterpriseServices.RegistrationException A registration error is detected None
EnterpriseServices.Serviced
ComponentException
An error is detected in a serviced component None
ExecutionEngineException There is an internal error in the execution engine of the common language runtime None
FormatException The format of an argument does not meet the parameter specifications of the invoked method Net.CookieException

Reflection.CustomAttribute
FormatException

UriFormatException

IndexOutofRangeException Attempt made to access an element of an array with an index that is outside the bounds of the array None
InvalidCastException Invalid casting or explicit conversion None
InvalidOperationException A method call is invalid for the object's current state Net.ProtocolViolationException

Net.WebException

ObjectDisposedException

InvalidProgramException Programs contains invalid Microsoft intermediate language or metadata None
IO.InternalBufferOverflowException The internal buffer overflows None
IO.IOException An I/O error occurs IO.DirectoryNotFoundException

IO.EndOfStreamException

IO.FileLoadException

IO.FileNotFoundException

IO.PathTooLongException

Management.ManagementException Management error None
MemberAccessException Attempt to access a class member fails FieldAccessException

MethodAccessException

MissingFieldException

MissingMemberException

MissingMethodException

MulticastNotSupportedException There is an attempt to combine two instances of a non-combinable delegate type where neither operand is a null reference None
NotImplementedException A requested method or operation is not implemented None
NotSupportedException Invoked method is not supported or there is an attempt to read, seek, or write to a stream that does not support the invoked functionality PlatformNotSupportedException
NullReferenceException Attempt to dereference a null object reference None
OutOfMemoryException Not enough memory to complete the execution of a program None
RankException Array with the wrong number of dimensions is passed to a method None
Reflection.AmbiguousMatch
Exception
Binding to a method results in more than one method matching the binding criteria None
Reflection.ReflectionType
LoadException
The Module.GetTypes method determines that one or more of the classes in a module cannot be loaded None
Resources.MissingManifest
ResourceException
Main assembly does not contain the resources for the neutral culture, but they are required because of a missing appropriate satellite assembly None
Runtime.InteropServices.
ExternalException
Base exception type for all COM interop exceptions and structured exception handling exceptions ComponentModel.Design.
CheckoutException

ComponentModel.Win32Exception

Data.OleDb.OleDbException

Messaging.MessageQueueException

Runtime.InteropServices.COMException

Runtime.InteropServices.SEHException

Web.HttpException

Runtime.InteropServices.
InvalidComObjectException
An invalid COM object is used None
Runtime.InteropServices.
InvalidOleVariantTypeException
The marshaler encounters an argument of a variant type that cannot be marshaled to managed code None
Runtime.InteropServices.
MarshalDirectiveException
The marshaler encounters a MarshalAsAttribute that it does not support None
Runtime.InteropServices.
SafeArrayRankMismatchException
Rank of an incoming SAFEARRAY does not match the rank specified in the managed signature None
Runtime.InteropServices.
SafeArrayTypeMismatchException
Type of an incoming SAFEARRAY does not match the type specified in the managed signature None
Runtime.Remoting.RemotingException Error occurs during remoting Runtime.Remoting.Remoting
TimeOutException
Runtime.Remoting.ServerException Used to communicate exception when the client connects to a non-.NET framework application that cannot throw exceptions None
Runtime.Serialization.SerializationException An error occurs during serialization or deserialization None
Security.Crytography.CryptographicException An error occurs during a cryptographic operation Security.Cryptography.
CryptographicUnexpected
OperationException
Security.Policy.PolicyException Policy forbids code to run None
Security.SecurityException A security error is detected None
Security.VerificationException A security policy requires that code be type safe and the verification process is not able to verify that the code is type safe None
Security.XmlSyntaxException Syntax error in XML parsing None
ServiceProcess.TimeoutException A specified timeout has expired None
StackOverflowException Overflow of the execution stack due to too many pending method calls None
Threading.SynchronizationLockException A synchronized method is invoked from an unsynchronized block of code None
Threading.ThreadAbortException Call made to the Abort method None
Threading.ThreadInterruptedException Thread interrupted while in a WaitSleepJoin state None
Threading.ThreadStateException Thread in an invalid ThreadState for the method call None
TypeInitializationException Thrown as a wrapper around the exception thrown by the class initializer None
TypeLoadException Type-loading failure DllNotFoundException

EntryPointNotFoundException

TypeUnloadedException Attempt to access an unloaded class None
UnauthorizedAccessException Operating system denies access because of an I/O error or a specific type of security error None
Web.Services.Protocols.SoapException Error occurs as a result of an XML Web service method being called over SOAP Web.Services.Protocols.
SoapHeaderException
Xml.Schema.XmlSchemaException   None
Xml.XmlException   None
Xml.Xpath.XpathException Error occurs when processing an Xpath expression None
Xml.Xsl.XsltException Error occurs when processing an Extensible StyleSheet Language (XSL) transform System.Xml.Xsl.XsltCompileException
Show:
© 2014 Microsoft