You can also define your own exception
objects to represent custom error conditions. All you need to do is
create an instance of the appropriate exception class and then use the
Throw statement.
The next example introduces a modified
DivideNumbers() method. It explicitly checks whether the specified
divisor is 0 and then manually creates and throws an instance of the
DivideByZeroException class to indicate the problem, rather than
attempt the operation. Depending on the code, this pattern can save
time by eliminating some unnecessary steps, or it can prevent a task
from being initiated if it can't be completed successfully.
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As EventArgs) Handles Me.Load
Try
DivideNumbers(5, 0)
Catch err As DivideByZeroException
' Report error here.
End Try
End Sub
Private Function DivideNumbers(ByVal number As Decimal, _
ByVal divisor As Decimal) As Decimal
If divisor = 0 Then
Dim err As New DivideByZeroException()
Throw err
Else
Return number/divisor
End If
End Function
Alternatively, you can create a .NET exception object and specify a custom error message by using a different constructor:
Private Function DivideNumbers(ByVal number As Decimal, _
ByVal divisor As Decimal) As Decimal
If divisor = 0 Then
Dim err As New DivideByZeroException( _
"You supplied 0 for the divisor parameter. You must be stopped.")
Throw err
Else
Return number/divisor
End If
End Function
In this case, any ordinary exception handler will
still catch the DivideByZeroException. The only difference is that the
error object has a modified Message property that contains the custom
string. Figure 1 shows the resulting exception.
Throwing an exception is most useful in
component-based programming. In component-based programming, your
ASP.NET page is creating objects and calling methods from a class
defined in a separately compiled assembly. In this case, the class in
the component needs to be able to notify the calling code (the web
application) of any errors. The component should handle recoverable
errors quietly and not pass them up to the calling code. On the other
hand, if an unrecoverable error occurs, it should always be indicated
with an exception and never through another mechanism (such as a return
code).
If you can find an exception in the class library
that accurately reflects the problem that has occurred, you should
throw it. If you need to return additional or specialized information,
you can create your own custom exception class.
Custom exception classes should always inherit from
System.ApplicationException, which itself derives from the base
Exception class. This allows .NET to distinguish between two broad
classes of exceptions—those you create and those that are native to the
.NET Framework.
When you create an exception class, you can add
properties to record additional information. For example, here is a
special class that records information about the failed attempt to
divide by zero:
Public Class CustomDivideByZeroException
Inherits ApplicationException
' Add a variable to specify the "other" number.
' Depending on the circumstance, this might help diagnose the problem.
Public DividingNumber As Decimal
End Class
NOTE
You can define the custom exception class
directly in your .aspx.vb code file. However, a more organized approach
is to use a separate code file. To do this, right-click your
application in the Solution Explorer, and choose Add New Item. Then,
pick Class from the list of templates, enter a file name, and click
Add. Visual Studio will place a new code file in the App_Code subfolder
of your website. (It's up to you whether you create a separate code
file for every class or put several classes in the same code file. Both
approaches have the same effect.)
You can throw this custom exception like this:
Private Function DivideNumbers(ByVal number As Decimal, _
ByVal divisor As Decimal) As Decimal
If divisor = 0 Then
Dim err As New CustomDivideByZeroException()
err.DividingNumber = number
Throw err
Else
Return number/divisor
End If
End Function
To perfect the custom exception, you need to supply
it with the three standard constructors. This allows your exception
class to be created in the standard ways that every exception supports:
On its own, with no arguments
With a custom message
With a custom message and an exception object to use as the inner exception
These constructors don't actually need to contain
any code. All these constructors need to do is forward the parameters
to the base class (the constructors in the inherited
ApplicationException class) using the MyBase keyword, as shown here:
Public Class CustomDivideByZeroException
Inherits ApplicationException
' Add a variable to specify the "other" number.
' Depending on the circumstance, this might help diagnose the problem.
Private _dividingNumber As Decimal
Public Property DividingNumber() As Decimal
Get
Return _dividingNumber
End Get
Set(ByVal value As Decimal)
_dividingNumber = value
End Set
End Property
Public Sub New()
MyBase.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 third constructor is particularly useful for
component programming. It allows you to set the InnerException property
with the exception object that caused the original problem. The next
example shows how you could use this constructor with a component class
called ArithmeticUtility:
Public Class ArithmeticUtilityException
Inherits ApplicationException
Public Sub New()
MyBase.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
Public Class ArithmeticUtility
Private Function Divide(ByVal number As Decimal, _
ByVal divisor As Decimal) As Decimal
Try
Return number/divisor
Catch err As Exception
' Create an instance of the specialized exception class,
' and place the original exception object (for example, a
' DivideByZeroException) in the InnerException property.
Dim errNew As New ArithmeticUtilityException("Calculation error", _
err)
' Now throw the new exception.
Throw errNew
End Try
End Function
End Class
Remember, custom exception classes are
really just a standardized way for one class to communicate an error to
a different portion of code. If you aren't using components or your own
utility classes, you probably don't need to create custom exception
classes.