![]() |
The .NET Framework Support for Exception Handling |
|
A Review of .NET Exception Classes |
|
Introduction |
|
The .NET Framework provides various classes to handle almost any type of exception you can think of. There are so many of these classes that we can only mention a few. There are two main ways you can use one of the classes of the .NET Framework. If you know for sure that a particular exception will be produced, pass its name to a Catch clause. Then, in the Catch section, display a custom message. The second option you have consists of using the Throw keyword. We will study it later. |
|
In most cases, we will try to always indicate the type of exception that could be thrown if something goes wrong in a program.
Everything the user types into an application using the keyboard is primarily a string and you must convert it to the appropriate type before using it. When you request a specific .NET type of value from the user, after the user has typed it and you decide to convert it to the appropriate type, if your conversion fails, the program produces (we will use he word "throw") an error. The error is of from the FormatException class. Here is a program that deals with a FormatException exception: Imports System.Drawing
Imports System.Windows.Forms
Module Exercise
Public Class Starter
Inherits Form
Private lblNumber As Label
Private txtNumber As TextBox
Friend WithEvents btnCalculate As Button
Private lblResult As Label
Private txtResult As TextBox
Dim components As System.ComponentModel.Container
Public Sub New()
InitializeComponent()
End Sub
Public Sub InitializeComponent()
Text = "Exceptional Behavior"
lblNumber = New Label
lblNumber.Location = New Point(17, 23)
lblNumber.Text = "Number:"
lblNumber.AutoSize = True
txtNumber = New TextBox
txtNumber.Location = New Point(78, 20)
txtNumber.Size = New Size(83, 20)
btnCalculate = New Button
btnCalculate.Location = New Point(78, 45)
btnCalculate.Text = "Calculate"
btnCalculate.Size = New Size(83, 23)
lblResult = New Label
lblResult.Location = New Point(17, 75)
lblResult.Text = "Result:"
lblResult.AutoSize = True
txtResult = New TextBox
txtResult.Location = New Point(76, 72)
txtResult.Size = New Size(83, 20)
Controls.Add(lblNumber)
Controls.Add(txtNumber)
Controls.Add(btnCalculate)
Controls.Add(lblResult)
Controls.Add(txtResult)
End Sub
Private Sub CalculateClicked(ByVal sender As Object, _
ByVal e As EventArgs) _
Handles btnCalculate.Click
Dim Number As Double
Dim Result As Double
Try
Number = Double.Parse(txtNumber.Text)
Result = Number * 12.48
txtResult.Text = CStr(Result)
Catch ex As FormatException
MsgBox("Inavlid Value!")
End Try
End Sub
End Class
Function Main() As Integer
Dim frmStart As Starter = New Starter
Application.Run(frmStart)
Return 0
End Function
End Module
A computer application receives, processes, and produces values on a regular basis as the program is running. To better manage these values, as we saw when studying variables and data types, the compiler uses appropriate amounts of space to store its values. It is not unusual that either you the programmer or a user of your application provides a value that is beyond the allowed range based on the data type. For example, a byte uses 8 bits to store a value and a combination of 8 bits can store a number no more than 255. If you provide a value higher than 255 to be stored in a byte, you get an error. Consider the following program: Private Sub CalculateClicked(ByVal sender As Object, _
ByVal e As EventArgs) _
Handles btnCalculate.Click
Dim Number As Byte
Dim Result As Byte
Try
Number = Byte.Parse(txtNumber.Text)
Result = Number * 12
txtResult.Text = CStr(Result)
Catch ex As FormatException
MsgBox("Inavlid Value!")
End Try
End Sub
When a value beyond the allowable range is asked to be stored in memory, the compiler produces (the verb is "throws" as we will learn soon) an error of the OverflowException class. Here is an example of running the program with a bad number: ![]() As with the other errors, when this exception is thrown, you should take appropriate action.
Once again, in a .NET Framework application, a value is passed to the Parse() method of its data type for analysis. For a primitive data type, the Parse() method scans the string and if the converted value is beyond a determined range, the compiler throws an ArgumentOutOfRangeException exception.
Division by zero is an operation to always avoid. It is so important that it is one of the most fundamental exceptions of the computer. It is addressed at the core level even by the processors. It is also addressed by the operating systems at their level. It is also addressed by most, if not all, compilers. It is also addressed by most, if not, all libraries. This means that this exception is never welcomed anywhere. The .NET Framework also provides it own class to face this operation. If an attempt to divide a value by 0, the compiler throws a DivideByZeroException exception.
As mentioned above, the Exception class is equipped with a Message property that carries a message for the error that occurred. We also mentioned that the message of this property may not be particularly useful to a user. Fortunately, you can create your own message and pass it to the Exception object. To be able to receive custom messages, the Exception class provides the following constructor: Public Sub New(message As String) To use it, in the section where you are anticipating the error, type the Throw keyword followed by a New instance of the Exception class using the constructor that takes a string. Here is an example: Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim Operand1 As Double
Dim Operand2 As Double
Dim Result As Double = 0.0
Dim Oper As String = "."
Try
Operand1 = Double.Parse(TextBox1.Text)
Oper = TextBox2.Text
Operand2 = Double.Parse(TextBox3.Text)
If (Oper <> "+") And _
(Oper <> "-") And _
(Oper <> "*") And _
(Oper <> "/") Then
Throw New Exception(Oper)
End If
Select Case Oper
Case "+"
Result = Operand1 + Operand2
Case "-"
Result = Operand1 - Operand2
Case "*"
Result = Operand1 * Operand2
Case "/"
Result = Operand1 / Operand2
Case Else
MsgBox("Bad Operation")
End Select
TextBox4.Text = CStr(Result)
Catch Ex As Exception
MsgBox("Operation Error: " & Ex.Message & _
vbCrLf & Oper & " is not a valid operator")
End Try
End Sub
In the above examples, when we anticipated some type of problem, we instructed the compiler to use our default catch section. We left it up to the compiler to find out when there was a problem and we provided a catch section to deal with it. A method with numerous or complex operations and requests can also produce different types of errors. With such a type of program, you should be able to face different problems and deal with them individually, each by its own kind. To do this, you can create different catch sections, each made for a particular error. The formula used would be: Try ' Code to Try Catch Arg1 ' One Exception Catch Arg2 ' Another Exception End Try The compiler would proceed in a top-down:
Multiple catches are written if or when a try block is expected to throw different types of errors. For example, in our calculator, we want to consider only the addition, the subtraction, the multiplication, and the division. It is also likely that the user may type one or two invalid numbers. This leads us to know that our program can produce at least two types of errors at this time. Based on this, we can address them using two catch clauses as follows: Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim Operand1 As Double
Dim Operand2 As Double
Dim Result As Double = 0.0
Dim Oper As String = "."
Try
Operand1 = Double.Parse(TextBox1.Text)
Oper = TextBox2.Text
Operand2 = Double.Parse(TextBox3.Text)
If (Oper <> "+") And _
(Oper <> "-") And _
(Oper <> "*") And _
(Oper <> "/") Then
Throw New Exception(Oper)
End If
Select Case Oper
Case "+"
Result = Operand1 + Operand2
Case "-"
Result = Operand1 - Operand2
Case "*"
Result = Operand1 * Operand2
Case "/"
Result = Operand1 / Operand2
Case Else
MsgBox("Bad Operation")
End Select
TextBox4.Text = CStr(Result)
Catch ex As FormatException
MsgBox("You type an invalid number. Please correct it")
Catch Ex As Exception
MsgBox("Operation Error: " & Ex.Message & _
vbCrLf & Oper & " is not a valid operator")
End Try
End Sub
This program works fine as long as the user types two valid numbers and a valid arithmetic operator. Anything else, such an invalid number or an unexpected operator would cause an error to be thrown:
Obviously various bad things could happen when this program is running. Imagine that the user wants to perform a division. You need to tell the compiler what to do if the user enters the denominator as 0 (or 0.00). If this happens, one of the options you should consider is to display a message and get out. Fortunately, the .NET Framework provides the DivideByZeroException class to deal with an exception caused by division by zero. As done with the message passed to the Exception class, you can compose your own message and pass it to the DivideByZeroException(string message) constructor. Exception is the parent of all exception classes. It corresponds to the type of Catch that takes no argument. Therefore, if you write various catch blocks, the one that either takes nor argument or is of the Exception type must be the last. Here is an example that catches two types of exceptions: Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim Operand1 As Double
Dim Operand2 As Double
Dim Result As Double = 0.0
Dim Oper As String = "."
Try
Operand1 = Double.Parse(TextBox1.Text)
Oper = TextBox2.Text
Operand2 = Double.Parse(TextBox3.Text)
If (Oper <> "+") And _
(Oper <> "-") And _
(Oper <> "*") And _
(Oper <> "/") Then
Throw New Exception(Oper)
End If
Select Case Oper
Case "+"
Result = Operand1 + Operand2
Case "-"
Result = Operand1 - Operand2
Case "*"
Result = Operand1 * Operand2
Case "/"
If Operand2 = 0 Then
Throw New DivideByZeroException("Division by zero is not allowed")
End If
Result = Operand1 / Operand2
Case Else
MsgBox("Bad Operation")
End Select
TextBox4.Text = CStr(Result)
Catch ex As FormatException
MsgBox("You type an invalid number. Please correct it")
Catch ex As DivideByZeroException
MsgBox(ex.Message)
Catch
MsgBox("Invalid Operation: " & vbCrLf & Oper & " is not a valid operator")
End Try
End Sub
The calculator simulator we have studied so far performs a division as one of its assignments. We learned that, in order to perform any operation, the compiler must first make sure that the user has entered a valid operator. Provided the operator is one of those we are expecting, we also must make sure that the user typed valid numbers. Even if these two criteria are met, it is still possible that the user would enter 0 for the denominator. The block that is used to check for a non-zero denominator depends on the exception that validates the operators. The exception that could result from a zero denominator depends on the user first entering a valid number for the denominator. You can create an exception inside of another. This is referred to as nesting an exception. This is done by applying the same techniques used to nest conditional statements. This means that you can write an exception that depends on, and is subject to, another exception. To nest an exception, create a Try clause in the body of the parent exception. The nested Try clause must be followed by its own Catch clause(s). To effectively handle the exception, make sure you include an appropriate Throw in the Try block. Here is an example: Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim Operand1 As Double
Dim Operand2 As Double
Dim Result As Double = 0.0
Dim Oper As String = "."
Try
Operand1 = Double.Parse(TextBox1.Text)
Oper = TextBox2.Text
Operand2 = Double.Parse(TextBox3.Text)
If (Oper <> "+") And _
(Oper <> "-") And _
(Oper <> "*") And _
(Oper <> "/") Then
Throw New Exception(Oper)
End If
Select Case Oper
Case "+"
Result = Operand1 + Operand2
TextBox4.Text = CStr(Result)
Case "-"
Result = Operand1 - Operand2
TextBox4.Text = CStr(Result)
Case "*"
Result = Operand1 * Operand2
TextBox4.Text = CStr(Result)
Case "/"
Try
If Operand2 = 0 Then
Throw New DivideByZeroException( _
"Division by zero is not allowed")
End If
Result = Operand1 / Operand2
Catch ex As DivideByZeroException
MsgBox(ex.Message)
End Try
Case Else
MsgBox("Bad Operation")
End Select
Catch ex As FormatException
MsgBox("You type an invalid number. Please correct it")
Catch
MsgBox("Invalid Operation: " & vbCrLf & _
Oper & " is not a valid operator")
End Try
End Sub
One of the most effective techniques used to deal with code is to isolate assignments in different functions. For example, the Select Case statement that was performing the operations in the “normal” version of our program could be written as follows: Private Function Calculate(ByVal Value1 As Double, _
ByVal Value2 As Double, _
ByVal symbol As Char) As Double
Dim Result As Double = 0.0
Select Case symbol
Case "+"
Result = Value1 + Value2
Case "-"
Result = Value1 - Value2
Case "*"
Result = Value1 * Value2
Case "/"
Result = Value1 / Value2
End Select
Calculate = Result
End Function
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim Operand1 As Double
Dim Operand2 As Double
Dim Result As Double = 0.0
Dim Oper As String = "."
Try
Operand1 = Double.Parse(TextBox1.Text)
Oper = TextBox2.Text
Operand2 = Double.Parse(TextBox3.Text)
If (Oper <> "+") And _
(Oper <> "-") And _
(Oper <> "*") And _
(Oper <> "/") Then
Throw New Exception(Oper)
End If
If Oper = "/" Then
If Operand2 = 0 Then
Throw New DivideByZeroException("Division by zero is not allowed")
End If
End If
Result = Calculate(Operand1, Operand2, Oper)
TextBox4.Text = CStr(Result)
Catch ex As FormatException
MsgBox("You type an invalid number. Please correct it")
Catch ex As DivideByZeroException
MsgBox(ex.Message)
Catch
MsgBox("Invalid Operation: " & vbCrLf & Oper & " is not a valid operator")
End Try
End Sub
This is an example of running the program: ![]() You can still use regular functions that handle exceptions and each function can handle its own exception(s). Here is an example: Private Function Addition(ByVal Value1 As Double, _
ByVal Value2 As Double) As Double
Addition = Value1 + Value2
End Function
Private Function Subtraction(ByVal Value1 As Double, _
ByVal Value2 As Double) As Double
Subtraction = Value1 - Value2
End Function
Private Function Multiplication(ByVal Value1 As Double, _
ByVal Value2 As Double) As Double
Multiplication = Value1 * Value2
End Function
Private Function Division(ByVal Value1 As Double, _
ByVal Value2 As Double) As Double
Dim Result As Double = 0.0
Try
If Value2 = 0 Then
Throw New DivideByZeroException("Division by zero is not allowed")
End If
Result = Value1 + Value2
Catch ex As DivideByZeroException
MsgBox(ex.Message)
End Try
Division = Result
End Function
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim Operand1 As Double
Dim Operand2 As Double
Dim Result As Double = 0.0
Dim Oper As String = "."
Try
Operand1 = Double.Parse(TextBox1.Text)
Oper = TextBox2.Text
Operand2 = Double.Parse(TextBox3.Text)
If (Oper <> "+") And _
(Oper <> "-") And _
(Oper <> "*") And _
(Oper <> "/") Then
Throw New Exception(Oper)
End If
Select Case Oper
Case "+"
Result = Addition(Operand1, Operand2)
Case "-"
Result = Subtraction(Operand1, Operand2)
Case "*"
Result = Multiplication(Operand1, Operand2)
Case "/"
Result = Division(Operand1, Operand2)
End Select
TextBox4.Text = CStr(Result)
Catch ex As FormatException
MsgBox("You type an invalid number. Please correct it")
Catch ex As DivideByZeroException
MsgBox(ex.Message)
Catch
MsgBox("Invalid Operation: " & vbCrLf & Oper & " is not a valid operator")
End Try
End Sub
|
|
|
||
| Previous | Copyright © 2008-2009, yevol.com | Next |
|
|
||