The Try and End Try statements are both required. The Catch and Finally statements may both be used in a Try block, but at least one of them is required. Also, multiple Catch statements are allowed to handle different types of exceptions. If you have multiple Catch blocks, order them from the most specific type of exception to the least specific:

Try
' Code that could raise an exception.
Catch ex As ArgumentOutOfRangeException
' Handle an invalid argument possibly using a default
' value so the code can continue
Catch ex As Exception
' Handle any other type of exception
Finally
' Code to cleanup (close database connections, etc.).
End Try

You also can throw exceptions in your code. This is useful when you catch an exception in part of your code, perform some cleanup code, and then throw the exception so a higher-level procedure can catch it. Throwing exceptions is also useful when creating custom exception types.

To throw an exception, you would write something like this:

Throw New ArgumentOutOfRangeException

ArgumentOutOfRangeException tells the Throw statement what type of exception to throw. The ArgumentOutOfRangeException type is just one of the many that the .NET Framework provides.

Propagating Exceptions

When an exception occurs somewhere in your code, you can propagate it in three ways:

Do nothing and let it propagate back up the call stack automatically.

Catch it and re-throw it. This allows you to run some cleanup code in the Finally block.

Catch it, wrap the exception in another exception using the InnerException property, and throw the new exception back to the calling procedure. The InnerException property lets you maintain the original exception and its information inside a more relevant exception.

Introducing Custom Exceptions

Although the .NET Framework provides many standard exceptions, you also can create, throw, and catch your own custom exceptions. In general, Microsoft recommends that you use the standard exceptions provided by the .NET Framework. However, if your application has a need that a standard exception does not satisfy, you can create a custom exception.

When you create a custom exception type, you gain control of all of the exceptions properties. You also can add properties to your custom exception class. This gives you a place to store crucial pieces of data besides embedding them in the Message property. This makes retrieval of the crucial data simple without parsing them out of the Message property.

Custom Exception Sample Application

The code package includes a very simple MS Access database that contains one table, named Customer. Not surprisingly, the Customer table contains a list of customers with ID, first name, last name, and address details. The actual contents of the database are not important, but data access is a good context for your custom exception.

For the application, I created a new console application in the VB 2005 Express IDE.

DatabaseException Base Class

If you're going to have more than one custom exception, it's a good idea to create a custom base class for them. This base class will inherit from the System.Exception class that the .NET Framework provides. It also will contain the three constructors that will be common to all of your custom exceptions. The sample application's base class is called DatabaseException; the code is listed below:

Public Class DatabaseException
Inherits Exception
Public Sub New()
End Sub
Public Sub New(ByVal message As String)
MyBase.New(message)
End Sub
Public Sub New(ByVal message As String, ByVal inner As Exception)
MyBase.New(message, inner)
End Sub
End Class

The three constructors are the standard constructors provided by the System.Exception class. The first allows you to create an exception without using any parameters, just the default exception properties. The second allows you to specify a message string to use as the Message property of your exception. Finally, the third constructor also allows you to specify the message string, but it lets you specify an exception as the second parameter as well. The System.Exception class has a property called InnerException that is useful when you catch an exception and want to wrap it inside a more relevant exception. By setting the InnerException property, you can maintain all of the information in the original exception.

One last note about the base class: There seems to be some disagreement as to whether you should inherit from the System.Exception class or the System.ApplicationExeption class. Most of the older literature from Microsoft states you should inherit from System.ApplicationException, but the new philosophy seems to state that you should instead inherit from the System.Exception class. I'm not sure what, if any, technical differences there are, but I tested with the base class inheriting from each and it works both ways. For the purposes of the sample application, follow the newer philosophy and inherit from System.Exception. Perhaps exploring this difference is fodder for a future article.

Custom Exception: CustomerNotFoundException

The first custom exception class is called CustomerNotFoundException. You will throw this exception when you attempt to look up a customer in your database but do not find a match. The code is listed below:

Public Class CustomerNotFoundException
Inherits DatabaseException
Private m_CustomerID As Long
Public ReadOnly Property CustomerID() As Long
Get
Return m_CustomerID
End Get
End Property
Public Sub New(ByVal customerID As Long)
MyBase.New("Customer ID was not found.")
m_CustomerID = customerID
End Sub
End Class

This class inherits from the DatabaseException base class you created earlier. It contains only one constructor, which takes the customerID as a parameter. When this constructor is called, you pass the text string "Customer ID was not found." into the constructor of the base class to be used as the Message property. You also have a readonly property called CustomerID defined. You will use the CustomerID property to store the value of the customer ID that was passed in as a parameter. It is a readonly property because it does not make any sense to change the value to something other than the value that caused the exception.

Custom Exception: DatabaseUnavailableException

The second custom exception class is called DatabaseUnavailableException. You will throw this exception when an exception occurs while you're attempting to connect to the database. The code is listed below:

Public Class DatabaseUnavailableException
Inherits DatabaseException
Public Sub New(ByVal ex As Exception)
MyBase.New("The database is not available.", ex)
End Sub
End Class

This class is very similar to your CustomerNotFoundException class. You do not have any additional properties defined for this class, but the primary difference is that it takes a System.Exception as a parameter and passes it into the constructor in your base class. This System.Exception parameter will become the InnerException property of your DatabaseUnavailableException.

Customer Class

The Customer class is a simple class that takes a database name and a customer ID as parameters for the constructor and attempts to retrieve the data for that customer. The first thing the constructor does is attempt to connect to the database by using the ConnectDB method as follows:

You attempt to open the database connection inside a Try statement. If any exception is thrown, you catch it and throw a DatabaseUnavailableException, wrapping the original exception in its InnerException property.

If you make a successful connection to the database, you then try to retrieve the data for the specified customer ID using the GetCustomer method as follows:

You execute a SQL query using the customerID to specify which customer's data you want to retrieve. If the query returns a result, you set the properties of the Customer class using the values returned by the query. But, if you do not get any data, you throw a CustomerNotFoundException using the customerID as a parameter for the constructor. This value will be used to set the CustomerID property of your CustomerNotFoundException object.

App in Action

The following screenshots show your application in action. To run the application, call it from a command prompt and specify a database name and customer ID as arguments. The three screen shots show a successful query (see Figure 1), a CustomerNotFoundException being thrown (see Figure 2), and a DatabaseNotAvailableException being thrown (see Figure 3).

Figure 1. Successful Query

Figure 2. CustomerNotFoundException

Figure 3. DatabaseUnavailableException

Wrapping It Up

Custom exception types are a powerful feature of the VB .NET language. The .NET Framework provides many standard exception types that will suffice for most needs. In fact, you may rarely use anything but the standard exceptions, but the ability to create custom exceptions is a powerful tool to have.

Download the Code

About the Author

Josh Fitzgerald is an applications development group leader for a large medical device company in Warsaw, Indiana. Designing and developing Visual Basic .NET applications is only one of his responsibilities, but it is his favorite part of his job. You can reach Josh at josh.fitzgerald@gmail.com.