VB.NET Exception Handling

Exception Handling,Handling Multiple Exceptions,Generic Catch-block With No Exception Information,Handling Multiple Exceptions,Throwing Exceptions,Custom Exceptions,Custom Exceptions,exception
Share it:
VB.NET Exception Handling



Introduction


Hardly any software is without any problems. Programmers do make mistakes when writing, despite what some may claim, as writing software can be a complex task. Problems that arise when a given software is taken in usage may be due to the wrong usage on the side of user or bade code written by the programmer or perhaps a rare scenario that the programmer could not or has not taken into consideration at the time the software was written. No matter what the source of problems is, the truth is that they do occur. These problems are known as exceptions because they are situations that are not normal.



To deal with exceptions, the .NET framework provides us with an exception handling mechanism. Exception handling enables us to take care of situations where our software may otherwise fail to do a job or crash totally because some resource is not available or could not be found.


Exception Handling


When we write code that handles exceptions, we, in essence, say: Try to carry out a certain task and if it fails then do some other job. This other job may be that we want to log what happened and why we could not carry out the original task. This information may then be conveyed to the user of the application. What we achieve with this is that firstly our application does not crash. Secondly, it logs the source that caused the exception and this logged information can later be used to handle the exception in the application. Let's take a look at a simple line of code that, when executed, crashes the application.


Exception Handling





result = 5 / 0
It's mathematically undefined to divide a number by zero. When we try to execute the line of code, we get an error and our application crashes for the very same mathematical reason! In other words, we have an exception. How we can handle this exception so that our application does not crash is what we will look at in a while. But first, we need to have a closer look at exceptions in the .NET framework.


The Exception Base Class



The Exception class (in System.Exception) is the base class for any kind of exception whether it is user-defined or .NET defined. When you have to deal with exceptions that are not already covered by the .NET framework, you will have to derive from the System. Exception classes, which are called custom exceptions. More on this later in the article.



The exception handling code has three sections. These three sections are presented below.





 Try
            'Section 1: Try-block   
        Catch ex As Exception
            'Section 2: Catch-block 
        Finally
            'Section 3: Finally-block   
        End Try




Section 1 is called the try-block and contains code that we want to execute and that may throw exceptions.

Section 2 is called the catch-block and contains code that we want to execute if the code in the try-block throws an exception. This is the ideal place to log information about the exception and perhaps inform the user that an exception was thrown. If no information is to be logged, then you can skip this block. The local variable ex (you can name it whatever you want, of course) holds a reference to the thrown exception (in this case the base Exception). The local exception variable gives access to lots of useful information about the exception itself - like a string message that explains why the exception was thrown. Instead of catching the base exception, as in this example, you can, of course, catch specific thrown exceptions. We will look into this shortly.






Lastly, Section 3 is called the finally-block and this is the block that gets executed whether or not an exception is thrown. This section is usually used to free external resources such as database connections, Windows handles and so on. If you do not have such stuff to clean up then you do not need this block. You cannot have the try-block alone. It must be accompanied by either the catch-block, finally-block or both of them. The legal combinations of the three blocks are shown below.





Try
            'Section 1
        Catch ex As Exception
            'Section 2
        Finally
            'Section 3
        End Try

        Try
            'Section 1
        Catch ex As Exception
            'Section 2
        End Try

        Try
            'Section 1
        Finally
            'Section 3
        End Try




The first combination has all three blocks. This gives you a chance to both log information about the thrown exception in the catch-block and later do any cleaning-up of external resources, that you have used in the try-block, in the finally-block - this block is guaranteed to execute no matter what. It's, therefore, an ideal place for cleaning-up of any external resources. The second combination is like the first one except you do not have the finally-block. The third and final combination completely skips the catch-block. This is perfectly fine as you most likely do not need to log any information about the thrown exception.

Generic Catch-block With No Exception Information


As mentioned earlier, our ex variable holds a reference to the exception that was thrown. If you do nothing with the thrown exception (i.e. you swallow it) then you can completely skip its usage as shown below. But of course, the only thing you then know in such a catch-block is the fact that an exception was thrown. You can not know any other information about it.


Try

        Catch

        End Try


Now we will add exception handling code to the line of code presented above ?? where??. This is presented below. We have put the line of code in a try-block because this is the line that throws an exception. When the exception is thrown, the control is transferred to the catch-block where we show the string message coming from the caught exception (using its ex.Message property) to the user. Thus we have prevented the application from crashing and let the user know about the situation.



Try
            c = a / b
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try


Since we catch the base exception, we catch all possible exceptions that may get thrown in the try-block (by perhaps code not shown in our example) even though the actual exception thrown by the line of code is called DivideByZeroException.


Handling Multiple Exceptions


Often, we are interested in catching specific exceptions and handling them accordingly. If we have multiple lines of code in the try-block that each throws a different kind of exception or have a single method call in the try-block that throws multiple exceptions (to address different situations), then we can add multiple catch-blocks to handle them. An example of this is shown below.


  Try
            File.OpenText(filePath)
        Catch fnf As FileNotFoundException
            'We end up here if the file represented by 
            'filePath is not found
        Catch an As ArgumentNullException
            'We end up here if the filePath is Nothing (null)
        Catch ex As Exception
            'For all other exceptions, we end up here
        End Try

If you examine the File. In the OpenText method in the .NET documentation, you will find out that it throws many different exceptions. We can add a catch-block for each of them and then handle it accordingly. In the example, only two specific exceptions thrown by the method are handled, FileNotFoundException an ArgumentNullException. In the end, we have added a generic catch-block that handles all other exceptions. If you add the generic catch-block first and the specific ones after it, then you will always end up in the generic catch-block as that would be the one that is examined first! So add specific catch-blocks first and generic ones at the end for the correct behavior.


Throwing Exceptions


Just as exceptions can be caught, they can also be thrown. Throwing of an exceptions means that some error has occurred that makes it impossible to continue execution of an application in the normal fashion. Exceptions can be thrown using the throw keyword. The keyword can be used in two different ways to achieve two different results. They are explained below.

1) If you use the throw keyword followed by an exception, you actually throw a new exception.


  If index = -1 Then
            Throw New ArgumentException("The index must be positive")
        End If
If you use the throw keyword followed by a reference to an exception, you re-throw a caught exception (because having a reference to an exception means that you must have caught it.
  Try
            'Code that may throw an exception
        Catch ex As Exception
            Throw ex
        End Try

Why do we catch an exception, in the first place, just to re-throw it? Well, maybe you want to log any information about the exception and then re-throw it so that the calling methods know that an exception occurred. You let the exception bubble up the chain of method calls so that every method knows about the exception and can, therefore, take appropriate action. Re-throwing an exception in this manner resets the stack trace information (represented by the StackTrace class) of the exception to the place from where it was re-thrown. It is as if the exception just got thrown from here for the first time!


2) If you omit the exception name or reference when you use the throw keyword, then you re-throw the exception (same as earlier) but you also preserve the stack trace information of the exception. But what exception is re-thrown when we do not specify it? Well, using the throw keyword only is only allowed in the catch-block where we catch exceptions. In this block, we have a reference to the caught exception and its this one that is re-thrown with stack trace information preserved. This is demonstrated below.


  Try
            'Code that may throw an exception
        Catch ex As Exception
            Throw
        End Try


Custom Exceptions

Custom Exceptions

The .NET framework ships with lots of pre-developed exceptions that cover most of the common exception types. As a rule of thumb, you should always use these already-provided exceptions in your applications whenever possible. You can, however, make your own custom exceptions that deal with anomalies in your application.

In .NET, exceptions have been divided into two main categories that are represented by the System.SystemException and System.ApplicationException base classes. Both of these classes derive from the ultimate exception base class System. Exception. As the names imply, SystemException represents all those exceptions that are thrown by the Common Language Runtime CLR (or the .NET framework itself). This category of exceptions is fatal and applications can not recover from them. An example exception in this category is OutOfMemoryException. As the name implies, this exception is thrown by the CLR if your application goes out of memory. It's impossible for an application to continue execution when there is no more memory left.
ApplicationException, on the other hand, represents all those (non-fatal) exceptions that are thrown by the code in your application. This category of exceptions is non-fatal and applications can recover from them. Examples of such exceptions are NullRefrenceException, IndexOutOfRangeException, FileNotFoundException etc.

Having understood this distinction, you should always derive your custom exceptions from ApplicationException. Let's look at a simple example where we make our own customized exception.


Public Class CustomException
    Inherits ApplicationException

    Public Sub New(ByVal message As String)
        MyBase.New(message)
    End Sub

End Class

The code shows a custom exception called CustomException. By the way, all exceptions classes end with the word 'Exception' suffix. It's one of those good conventions like all interfaces start with the 'I' prefix e.g. IDisposable, IComparable etc. Getting back to our discussion, we start by inheriting from ApplicationException. This is so that our CustomException is considered a valid exception type in .NET. Next, we pass the incoming message to the base class that is accessible when the Message property is called on an instance of CustomException (because it's derived). The CustomException has the simplest form possible and it does not add anything exciting, but it can now be used like any other exception in your application. (I plan to extend the article on this topic)


Unhandled Exceptions


When your code throws an exception that you have not handled, the .NET framework displays a dialog box saying that a problem was encountered. Users can not use the dialog box for anything, but they are informed about the fact that an unhandled exception was thrown.

.NET does provide us with a mechanism to trap all unhandled exceptions in your application domain by attaching to two events called System.AppDomain.CurrentDomain.UnhandledException and System.Windows.Forms.Application.ThreadException. The first event is raised when an unhandled exception is thrown in a non-form thread or background thread. The second event is raised when an unhandled exception is thrown from within a forum thread. You would attach to one or both of these events depending on what you want to achieve. If it's a Windows service you are developing, for instance, then you may only want to attach to the first event as there are no forms in Windows services.

The two event handlers that we attach to the two events below are called OnUnhandledException and OnUnhandledGUIException respectively. These should be the first lines of code in your application entry-point - for instance the constructor.




Public Sub New()
       
        'Add these as the first lines where your applications start
        AddHandler UnhandledException, AddressOf OnUnhandledException
        AddHandler Application.ThreadException, AddressOf OnUnhandledGUIException

        'Other code here...

    End Sub


    'These are the actual event handlers
    Private Shared Sub OnUnhandledException(ByVal sender As Object, _
                                          ByVal e As UnhandledExceptionEventArgs)
        'Here you can log any information about the thrown unhandled exception
    End Sub

    Private Sub OnUnhandledGUIException(ByVal sender As Object, _
                                   ByVal e As Threading.ThreadExceptionEventArgs)
        'Here you can log any information about the thrown unhandled exception
    End Sub




                                      Share this article with your friends
Share it:

VB.NET

Post A Comment:

0 comments: