I used to develop in Visual Basic before the .NET days. To be honest, in some ways I preferred those tools. They were far simpler, and rather than worrying about how to implement something, you were more concerned with the implementation itself. Life seemed much simpler. However, one huge bugbear was the error handling. It was horrible, ugly and exceptionally difficult to develop a real good error handler. I wasn’t a fan. Then along came Visual Basic.NET and all that changed. The concepts of .NET error handling were (cough, cough) borrowed from Java, which borrowed them from Delphi (a great but now defunct language).I’m sure Delphi borrowed its core concepts from elsewhere. What is originality anyway? Undetected plagiarism…
So, what exactly is Error Handling in Visual Basic.NET? You may have heard Error Handling called Exception Handling? No? Well, let me explain. Errors occur in code. We all make mistakes. They may occur for a number of reasons. Your users may be doing something with your application that you didn’t anticipate in your code. You may have just made a mistake. It happens and we all do it. We’ve all seen applications or web sites break. How can we help prevent them breaking? By handling the errors and handling them gracefully. Can you remember the tutorial on the Select Case statement? To recap, we developed a simple application that would determine if you were older or younger than my niece. Pretty cutting edge stuff! In that application, when prompted to enter an age, what would happen if you entered the letter “e”? Your program would go boom! An error would occur as Visual Basic would try to convert the letter e to a number, fail to do so, and Visual Basic would report this back to you and stop running.
Look at the code in the button click event again:
</span> <pre>Dim age As Integer age = CInt(TextBoxAge.Text) Select Case age Case Is < 3 MessageBox.Show("You are younger than Chris' niece") Case Is > 3 MessageBox.Show("You are older than Chris' niece") Case Else MessageBox.Show("You are 3, the same age as Chris' niece") End Select
Pay particular attention to this line:
age = CInt(TextBoxAge.Text)
The CInt function converts text into a number. For example, the CInt function would convert “4” into 4. However it has no idea what to do if you entered “e”. There is no numeric value for “e”.
I’m going to show you two ways to handle this error gracefully.
The first way would be to use an inbuilt Visual Basic Function called IsNumeric
Open up that project and replace the click event code with this:
</span> <pre> Dim age As Integer If Not IsNumeric(TextBoxAge.Text) Then MessageBox.Show("You must enter a number for your age", _ "Doh!", _ MessageBoxButtons.OK, _ MessageBoxIcon.Error) TextBoxAge.Focus() TextBoxAge.SelectAll() Exit Sub End If age = CInt(TextBoxAge.Text) Select Case age Case Is < 3 MessageBox.Show("You are younger than Chris' niece") Case Is > 3 MessageBox.Show("You are older than Chris' niece") Case Else MessageBox.Show("You are 3, the same age as Chris' niece") End Select
In this case entering the letter “e” for your age would result in the application warning you that the number isn’t numeric. In addition, after the error, the invalid text was immediately selected. You can edit the field immediately without clicking anywhere. Nice!
So what is that code actually doing?
The first line of the new block is an IF Statement saying:
If Not IsNumeric(TextBoxAge.Text)
The IsNumeric Function will return true if the passed string is numeric and false if not. The line is essentially saying, if the string isn’t number, execute the code in the IF block.
Within the IF block there are 3 lines of code:
MessageBox.Show("You must enter a number for your age", _ "Doh!", _ MessageBoxButtons.OK, _ MessageBoxIcon.Error)
This line will show a MessageBox telling the user that they must enter a number for their age. The Title of the MessageBox dialog is “Doh!”, I am instructing Visual Basic to put an OK button in the MessageBox and to put an Error Icon in the MessageBox (a big red cross). Try experimenting with these parameters, Intellisense will show you what’s available.
Underneath that line there are two lines:
These lines instruct Visual Basic to put focus, .i.e the mousepointer on that TextBox. It also selects the offending text. I hate it when applications don’t do this. They force me to click on the offending area, select the offending number and write over it. This guides the user’s attention and to the error and improves useability no end. Feel free to use this technique liberally!
Finally the instruction:
Does what it says on the tin, it instructs Visual Basic to Exit the Sub without executing any more lines of code.
This kind of error handling is perfect. You are anticipating the error before it happens and can handle the error very gracefully. Often though, we aren’t so lucky. We can’t anticipate everything, especially in a more complex app with many more inputs and controls. So what do we do?
Replace the click event code with this:
Dim age As Integer Try age = CInt(TextBoxAge.Text) Select Case age Case Is < 3 MessageBox.Show("You are younger than Chris' niece") Case Is > 3 MessageBox.Show("You are older than Chris' niece") Case Else MessageBox.Show("You are 3, the same age as Chris' niece") End Select Catch ex As Exception MessageBox.Show(ex.Message, ex.GetType().ToString()) Finally TextBoxAge.Focus() TextBoxAge.SelectAll() End Try
I’ve removed the IsNumeric text and instead wrapped the entire code block in a Try Block. This instructs Visual Basic to Try to execute the following code. If an error occurs, the code immediately executes the Catch block of code.
When an error occurs in Visual Basic, Visual Basic will create an Exception object. The line Catch ex As exception, will assign this Exception object to our local variable ex. The Exception object has a number of properties from which we can gleam what error occurred. We have utilised the Exception.Message property to display to the user. We have also output the Type of Exception as the title of the MessageBox. There are far more properties available to you in the Exception object allowing you to provide more detailed information on what went wrong. Try experimenting with the other properties.
Finally, no pun intended, The Finally block is then called. There are two circumstances a Finally block will be called. Either all the code in the Try block has been executed, or after the Catch code has been executed should an error be thrown. In this Finally block I have set the focus back on the TextBox and selected the text in there.
Run the project and try it, with valid or invalid values. What happens? With an invalid value you get the helpful error message of:
Huh? Well hopefully you understand what its saying; Visual Basic can’t convert the letter “e” to integer. However imagine being an end user of your application and reading that? For the title of this MessageBox, I output the type of error that had occurred – which turned out to be an System.InvalidCastException. Let’s make this a bit friendlier for our end users.
Replace the catch statement with this:
Catch invalidCastException As InvalidCastException MessageBox.Show("You must enter a number for your age") Catch ex As Exception MessageBox.Show(ex.Message, ex.GetType().ToString())
Run the application; enter the e and what happens? The system is giving a much more user friendly error to the user. Why? Well we have two catch blocks. One will catch all errors of type InvalidCastException, which we know will occur if the user doesn’t enter a number. The other catch which will catch all other errors. We can add as many different catch blocks as we like, but this catch all must go last in our catch blocks.
Which method of error handling do is preferable the first example of anticipating the error using the IF Statement, or the Try Catch Finally? I would use a combination of both and depends on the circumstances. Try Catches are absolutely essential in most enterprise apps as it’s physically impossible to anticipate all errors. However often it’s often a lot more elegant to validate the contents of a Form using an IF Statement. There are no right answers here, you must put thought into what makes the code more robust. Don’t let your application break, and if an error occurs, try to tell your users exactly what is going on. Your users will love you for it!