Normally, Exception mostly serves as the
general class of exceptions. Anticipating various types of problems that
can occur in a program, Microsoft derived various classes from Exception
to make this issue friendlier. As a result, almost any type of exception
you may encounter already has a class created to deal with it. Therefore,
when your program faces an exception, you can easily access the class
appropriate for that error. There are so many exception classes that we
cannot study or review them all. The solution we will use is to introduce
or review a class when we meet its type of error.
Practical Learning: Introducing Exception Handling
In exception handling, errors are dealt with in the Catch section. On the right side of Catch, behave as if you were declaring a variable of the type of exception you want to deal with. By default, an exception is first of type Exception. Based on this, a typical formula to implement exception handling is: Try ' Process the normal flow of the program here Catch Parameter As Exception ' Deal with the exception here End Try When an exception occurs in the Try section, code compilation is transferred to the Catch section. If you declare the exception as an Exception type, this class will identify the error. One of the properties of the Exception class is called Message. This property contains a string that describes the type of error that occurred. You can then use this Exception.Message property to display an error message if you want. Here is an example: Public Class Exercise Public Function Main() As Integer Dim Number As Double Try Console.Write("Type a number: ") Number = CDbl(Console.ReadLine()) Console.WriteLine(vbcrlf & "{0} * 2 = {1}", Number, Number * 2) Catch ex As Exception Console.WriteLine(ex.Message) End Try Return 0 End Sub End Class Here is an example of running the program: Type a number: 45KP2 Cast from string "45KP2" to type 'Double' is not valid.
As you can see, one of the strengths of the Exception.Message property is that it gives you a good indication of the type of problem that occurred. Sometimes, the message provided by the Exception class may not appear explicit enough. In fact, you may not want to show it to the user since, as in this case, the user may not understand what the word "Cast" in this context means and why it is being used. As an alternative, you can create your own message and display it to the user. Here is an example: Public Class Exercise Public Function Main() As Integer Dim Number As Double Try Console.Write("Type a number: ") Number = CDbl(Console.ReadLine()) Console.WriteLine(vbcrlf & "{0} * 2 = {1}", Number, Number * 2) Catch ex As Exception Console.WriteLine("The operation could not be carried because " & _ "the number you typed is not valid") End Try Return 0 End Sub End Class Here is an example of running the program: Type a number: 88D.46 The operation could not be carried because the number you typed is not valid You can also combine the Exception.Message message and your own message: Public Class Exercise Public Function Main() As Integer Dim Number As Double Try Console.Write("Type a number: ") Number = CDbl(Console.ReadLine()) Console.WriteLine(vbcrlf & "{0} * 2 = {1}", Number, Number * 2) Catch ex As Exception Console.WriteLine(ex.Message & vbCrLf & _ "The operation could not be carried because " & _ "the number you typed is not valid") End Try Return 0 End Sub End Class Here is an example of running the program: Type a number: 45PK12 Cast from string "45PK12" to type 'Double' is not valid. The operation could not be carried because the number you typed is not valid
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 the few that we regularly use in our application. 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 the Catch clause and display a custom message. The second option you have consists of using the throw keyword. We will study it later. From now on, we will try to always indicate the type of exception that could be thrown if something goes wrong in a program
When studying data formatting in Lesson 5, we saw that everything the user types into an application using the keyboard is primarily a string and that you must convert it to the appropriate type before using it. When you request a specific type of value from the user, after the user has typed it and you decide to convert it to the appropriate type using one of the built-in conversion functions (CDbl(), CInt, CDate, CSng, CDec, etc), if your conversion fails, the program produces (in the next lessons, we will use he word "throw") an error. The error is from the InvalidCastException class. Here is a program that deals with a InvalidCastException exception: Public Class Exercise Public Function Main() As Integer Dim Number As Double Try Console.Write("Type a number: ") Number = CDbl(Console.ReadLine()) Console.WriteLine("\n{0} * 2 = {1}", Number, Number * 2) Catch ex As InvalidCastException Console.WriteLine("You typed an invalid number") End Try Return 0 End Sub End Class Here is an example of running the program: Type a number: 39W.68g You typed an invalid number
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 in Lesson 2, 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 provide a value that is beyond the allowed range of 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: Public Class Exercise Public Function Main() As Integer Dim NumberOfPages As Byte Console.Write("Enter the number of pages of the newspaper: ") NumberOfPages = CByte(Console.ReadLine()) Console.WriteLine("Number of Pages of the Newspaper: {0}", NumberOfPages) Return 0 End Sub End Class When a value beyond the allowable range is asked to be stored in memory, the compiler produces (or "throws") an error of the OverflowException class. Here is an example of running the program: Enter the number of pages of the newspaper: 462 Unhandled Exception: System.OverflowException: Arithmetic operation resulted in an overflow. at Microsoft.VisualBasic.CompilerServices.ByteType.FromString(String Value) at Project5.Exercise.main() in C:\Programs\MSVB .NET 2003\Project5\Exercise.v b:line 8 As with the other errors, when this exception is thrown, you should take appropriate action.
Once again, when studying the techniques of converting or formatting values in Lesson 5, we saw that a value is passed to a conversion function for analysis. For a primitive data type, the conversion function scans the string and if the string cannot be converted into a valid character or number, the compiler usually throws an InvalidCastException exception as we saw above. Other data types such as Date also use use this technique to scan the value submitted to it. For example, if you request a date value from the user, the CDate() function scans the string to validate it. In US English, CDate() expects the user to type a string in the form m/d/yy or mm/dd/yy or mm/dd/yyyy or yyyy/mm/dd. Consider the following program: Public Class Exercise Public Function Main() As Integer Dim DateHired As Date Console.Write("Enter Date Hired: ") DateHired = DateTime.Parse(Console.ReadLine()) Console.WriteLine("Date Hired: {0:d}", DateHired) Return 0 End Sub End Class If the user types a value that cannot be converted into a valid date, the compiler throws an FormatException exception. Here is an example of running the above program: Enter Date Hired: 04/12/2002 Date Hired: 4/12/2002 Here is another example of running the program: Enter Date Hired: 1998/10/24 Date Hired: 10/24/1998 Here is one more example of running the program: Enter Date Hired: 16/04/2002 Unhandled Exception: System.FormatException: String was not recognized as a vali d DateTime. at System.DateTimeParse.GetDayOfNNY(DateTimeResult result, DateTimeRawInfo ra w, DateTimeFormatInfo dtfi) at System.DateTimeParse.ProcessTerminaltState(Int32 dps, DateTimeResult resul t, DateTimeRawInfo raw, DateTimeFormatInfo dtfi) at System.DateTimeParse.Parse(String s, DateTimeFormatInfo dtfi, DateTimeStyl es styles) at System.DateTime.Parse(String s, IFormatProvider provider, DateTimeStyles s tyles) at System.DateTime.Parse(String s, IFormatProvider provider) at System.DateTime.Parse(String s) at Project5.Exercise.main() in C:\Programs\MSVB .NET 2003\Project5\Exercise.v b:line 8 One way you can avoid this is to guide the user about the type of expected value. Here is an example: Public Class Exercise Public Function Main() As Integer Dim DateHired As Date Console.Write("Enter Date Hired (mm/dd/yyyy): ") DateHired = DateTime.Parse(Console.ReadLine()) Console.WriteLine("Date Hired: {0:d}", DateHired) Return 0 End Sub End Class You should still prepare to take appropriate actions, just in case this error is thrown.
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 Intel and AMD 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. We will see an example later. |
|
||||||||||||||||||||||||||||||||||||
|
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. To be able to receive custom messages, the Exception class provides the following constructor: public Exception(string message) To use it, in the section that 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: Public Class Exercise Public Function Main() As Integer Dim Number1 As Double, Number2 As Double Dim Operator As String Dim Result As Double Try Console.Write("Enter First Number: ") Number1 = CDbl(Console.ReadLine()) Console.Write("Enter Operation (+, -, *, or /): ") Operator = CStr(Console.ReadLine()) Console.Write("Enter Second Number: ") Number2 = CDbl(Console.ReadLine()) If Operator = "+" Then Result = Number1 + Number2 ElseIf Operator = "-" Then Result = Number1 - Number2 ElseIf Operator = "*" Then Result = Number1 * Number2 ElseIf Operator = "/" Then Result = Number1 / Number2 Else Result = 0 End If Console.WriteLine(vbCrLf & "{0} {1} {2} = {3}", _ Number1, Operator, Number2, Result) Catch ex as Exception Console.WriteLine( _ "Somewhere went wrong: your operation could not be performed") End Try Return 0 End Sub End Class Here is an example of running the program: Enter First Number: 244.98 Enter Operation (+, -, *, or /): * Enter Second Number: 24.52 244.98 * 24.52 = 6006.9096 Here is another example of running the program: Enter First Number: 405.66 Enter Operation (+, -, *, or /): - Enter Second Number: 24GD Something went wrong: your operation could not be performed Here is one more example of running the program: Enter First Number: 248.12 Enter Operation (+, -, *, or /): $ Enter Second Number: 5.15 248.12 $ 5.15 = 0
In the examples above, 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 One Type of Exception ' One Exception Catch Another Type Of Exception ' 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. This program works fine as long as the user types a valid sequence of values made of a number, a valid arithmetic operator, and a number. Anything else, such an invalid number, an unexpected operator, or a wrong sequence (such as a number then another number instead of an operator), would cause an error to be thrown. Obviously various bad things could happen when this program is running. To handle the exceptions that this program could produce, you can start with the most likely problem that would occur. Trusting that a user is able to provide the two numbers that are requested, it is possible that a user would type an invalid operator. For example, for this program we will perform only the addition (+), the subtraction(-), the multiplication(*), and the division(/). Therefore, we will first validate the operator. This can be done as follows: Public Class Exercise Public Function Main() As Integer Dim Number1 As Double, Number2 As Double Dim Operator As String Dim Result As Double Try Console.Write("Enter First Number: ") Number1 = CDbl(Console.ReadLine()) Console.Write("Enter Operation (+, -, *, or /): ") Operator = CStr(Console.ReadLine()) Console.Write("Enter Second Number: ") Number2 = CDbl(Console.ReadLine()) If Operator <> "+" And Operator <> "-" And _ Operator <> "*" And Operator <> "/" Then Throw New Exception(Operator) End If If Operator = "+" Then Result = Number1 + Number2 ElseIf Operator = "-" Then Result = Number1 - Number2 ElseIf Operator = "*" Then Result = Number1 * Number2 ElseIf Operator = "/" Then Result = Number1 / Number2 Else Result = 0 End If Console.WriteLine(vbCrLf & "{0} {1} {2} = {3}", _ Number1, Operator, Number2, Result) Catch ex As Exception Console.WriteLine(vbCrLf & "Invalid Operator: {0}", Operator) Console.WriteLine("Your operation could not be performed") End Try Return 0 End Sub End Class When this program runs, if the user provides a invalid operator, we register the operator by calling the Exception(string message) constructor and pass it the wrong operator. If this error occurs, the compiler gets out of the Try block, it starts looking for and finds a Catch clause that receives an Exception exception. Therefore, this Catch is executed. Here is an example of running the program: Enter First Number: 1255.85 Enter Operation (+, -, *, or /): + Enter Second Number: 704.62 1255.85 + 704.62 = 1960.47 Here is another example of running the same program: Enter First Number: 1255.85 Enter Operation (+, -, *, or /): @ Enter Second Number: 704.62 Invalid Operator: @ Your operation could not be performed Here is another example of running the progvram: Enter First Number: 124.05 Enter Operation (+, -, *, or /): / Enter Second Number: 0 124.05 / 0 = Infinity 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, the best option, and probably the only one 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. Therefore, if you write various catch blocks, the one that takes the Exception as argument must be the last. Here is an example that catches two types of exceptions: Public Class Exercise Public Function Main() As Integer Dim Number1 As Double, Number2 As Double Dim Operator As String Dim Result As Double Try Console.Write("Enter First Number: ") Number1 = CDbl(Console.ReadLine()) Console.Write("Enter Operation (+, -, *, or /): ") Operator = CStr(Console.ReadLine()) Console.Write("Enter Second Number: ") Number2 = CDbl(Console.ReadLine()) If Operator <> "+" And Operator <> "-" And _ Operator <> "*" And Operator <> "/" Then Throw New Exception(Operator) End If If Operator = "/" And Number2 = 0 Then Throw New DivideByZeroException("Division by zero is not allowed") End If If Operator = "+" Then Result = Number1 + Number2 ElseIf Operator = "-" Then Result = Number1 - Number2 ElseIf Operator = "*" Then Result = Number1 * Number2 ElseIf Operator = "/" Then Result = Number1 / Number2 Else Result = 0 End If Console.WriteLine(vbCrLf & "{0} {1} {2} = {3}", _ Number1, Operator, Number2, Result) Console.WriteLine() Catch ex As DivideByZeroException Console.WriteLine(ex.Message) Catch ex As Exception Console.WriteLine("Invalid Operator: {0}", Operator) Console.WriteLine("Your operation could not be performed") End Try Return 0 End Sub End Class When running this program, if the user types a wrong operator, the compiler gets out the Try block and looks for a Catch that takes an Exception as argument. It finds the second and executes it. If the user enters two valid numbers, then the compiler finds out if the operator entered was a forward slash “/” used to perform a division. If the user wants to perform a division, the compiler finds out if the second operand, the denominator, is 0. If it is, we create a DivideByZeroException instance and pass our own message to it. Based on this exception, the compiler gets out of the Try block and starts looking for a Catch block that considers a DivideByZeroException exception. It finds it in the first catch. Therefore, the compiler executes it. Here is an example of executing the program: Enter First Number: 1288.24 Enter Operation (+, -, *, or /): * Enter Second Number: 4.06 1288.24 * 4.06 = 5230.2544 Here is another example of executing the same program: Enter First Number: 125.85 Enter Operation (+, -, *, or /): / Enter Second Number: 5.05 125.85 / 5.05 = 24.9207920792079 Here is another example of executing the same program: Enter First Number: 808.82 Enter Operation (+, -, *, or /): / Enter Second Number: 0 Division by zero is not allowed
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 was possible that the user 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. You can create an exception inside of another. This is referred to as nesting an exception. This is done by applying the same techniques we 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, write a Try block in the body of the parent exception. The nested Try block must be followed by its own Catch(es) clause. To effectively handle the exception, make sure you include an appropriate Throw in the Try block. Here is an example: Public Class Exercise Public Function Main() As Integer Dim Number1 As Double, Number2 As Double Dim Operator As String Dim Result As Double Try Console.Write("Enter First Number: ") Number1 = CDbl(Console.ReadLine()) Console.Write("Enter Operation (+, -, *, or /): ") Operator = CStr(Console.ReadLine()) Console.Write("Enter Second Number: ") Number2 = CDbl(Console.ReadLine()) Console.WriteLine() If Operator <> "+" And Operator <> "-" And _ Operator <> "*" And Operator <> "/" Then Throw New Exception(Operator) End If If Operator = "+" Then Result = Number1 + Number2 Console.WriteLine(vbCrLf & "{0} {1} {2} = {3}", _ Number1, Operator, Number2, Result) ElseIf Operator = "-" Then Result = Number1 - Number2 Console.WriteLine(vbCrLf & "{0} {1} {2} = {3}", _ Number1, Operator, Number2, Result) ElseIf Operator = "*" Then Result = Number1 * Number2 Console.WriteLine(vbCrLf & "{0} {1} {2} = {3}", _ Number1, Operator, Number2, Result) ElseIf Operator = "/" Then Try If Number2 = 0 Then Throw New DivideByZeroException( _ "Division by zero is not allowed") End If Result = Number1 / Number2 Console.WriteLine(vbCrLf & "{0} {1} {2} = {3}", _ Number1, Operator, Number2, Result) Catch ex As DivideByZeroException Console.WriteLine(ex.Message) End Try Else Result = 0 End If Catch ex As Exception Console.WriteLine("Invalid Operator: {0}", Operator) Console.WriteLine("Your operation could not be performed") End Try Return 0 End Sub End Class Here is an example of running the program: Enter First Number: 125.55 Enter Operation (+, -, *, or /): / Enter Second Number: 42.05 125.55 / 42.05 = 2.98573127229489 Here is another example of running the program: Enter First Number: 125.55 Enter Operation (+, -, *, or /): / Enter Second Number: 0 Division by zero is not allowed |
|
|||||||||
|