Error Handling in Visual Basic.NET
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) which I’m sure borrowed it’s core concepts from elsewhere. What is originality anyway? Undetected plagiarism.
So, what is so good about 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 because of user error, because you didn’t anticipate something in your code, or just because you made a mistake. It happens. We’ve all seen applications or web sites break. How can we help prevent them breaking? By handling the errors and handling them gracefully.
Open project called “Select Case Statement”. Run the project and when prompted to enter an age, enter the letter “e” and press “Younger or Older”. What happens? Your program went boom! An error occurred, an unhandled error, so Visual Basic reported this to you and stopped running.
Look at the code in the button click event again
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</pre>
Why do you think it wouldn’t work? Look at this line:
age = CInt(TextBoxAge.Text)
If you remember, the CInt function converts text into a number. For example, it would convert “4” into 4. However it has no idea what to do if you entered “e”. There is no numeric value for “e”, so it raised an error.
I’m going to show you two ways to handle this error gracefully.
The first way would be to use a built Visual Basic Functions IsNumeric
Replace the click event code with this
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
Run your code, enter “e” for your age. What happens? Your application warns you that the number isn’t numeric! It works. 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. False if not. The line is essentially saying, if the string isn’t number, execute the code in the IF block. Does that make sense?
Within the 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 the Icon on the Messagebox is an Error symbol, or a big red cross. Try experimenting with these parameters, Intellisense will show you what’s available.
Underneath that line the two lines
TextBoxAge.Focus() TextBoxAge.SelectAll()
These lines instruct Visual Basic to put focus, ie 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
Exit Sub
Does what is says in 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 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 execution of code is immediately taken to the Catch block of code. When an error occurs in Visual Basic, Visual Basic will create an Exception object. Catch ex As exception will assign this Exception object to our variable ex. The Exception object has a number of properties from which we can gleam what error occured. 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 which will be worthwhile later in this tutorial. There is far more detailed information using other properties in the Exception object that will provide more information on what went wrong. Try experimenting with the other properties here.
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, it can’t convert the letter “e” to integer. However imagine being an end user 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.
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 code, 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. And another 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 I prefer? 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 – its physically impossible to anticipate all errors. However often it’s often a lot more elegant to validate form contents, and predictable elements using the IF Statement. 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 s going on. Your users will love you for it!