JabbaWook
JabbaWook

Reputation: 685

error handling continue point after error caught and handled

I have a large program I am upgrading in vb.net. I am programming the error handling so that the program can continue to operate even if there is an exception (file doesn't exist etc). But I have got myself confused with all the error handling.

If I have multiple methods that call each other and I put a try catch around the top level method, where is the point that the program will continue to run from after the exception is handled?

For e.g:

public Sub Main()
    Dim a As Integer
    Try
        If (Foo()) Then
            a = Boo()
        End If
    Catch
    End Try
    'Is a 10 here???
End Sub

public Function Foo() As Boolean
    Line1
    Line2
    Line3
    return True
End Function

Public Function Boo() As Int
    Line4
    Line5
    Line6
    return 10
End Function

Would Boo() be called no matter what in this case and a always = 10, for example? - Even if there were exceptions caused on lines 1-6?

Upvotes: 0

Views: 262

Answers (1)

Cody Gray
Cody Gray

Reputation: 245012

No, in your example, if Foo throws an exception, the Catch block will be entered immediately. The Boo function will not be called, and the value of a will not be set.

This would be true even if you Main function did not use any Try/Catch blocks:

Public Sub Main()
    Dim a As Integer
    If (Foo()) Then
        a = Boo()
    End If
End Sub

Boo() will only be called, and a will only be set to its result, if Foo does not throw an exception. If Foo throws, the runtime will search for a suitable exception handler. Not finding one, and this being the top-level method, you'll have an unhandled exception that will then cause the application to be terminated.

This is why exceptions should not be used for flow control, only for actual exceptional conditions.

Put only things that you expect to throw in a Try block, and only have Catch blocks for exceptions that you know how to handle. I would also recommend initializing variables in their declaration whenever possible. Some made-up code as an example of how this should logically work:

Public Sub Main()
    Dim val As Integer = 0    ' 0 is our "default" value

    ' Don't need a Try here, this won't throw an exception.
    ' It will just return an empty string if they canceled.
    Dim fileName As String = AskUserForFileName()

    ' See if they canceled...
    If (fileName <> String.Empty)
        Try
           ' Now we need a Try block, because we're going to do
           ' stuff that might throw an exception.
           Dim file As File = OpenFile(fileName)

           ' Execution won't get here if OpenFile() threw an exception, so
           ' at this point, we know that the file was opened successfully,
           ' so we'll try to read our value from it.
           val = ReadDataFromFile(file)

           ' Again, execution won't get here if ReadDataFromFile() threw
           ' an exception, so we know that the data was read out successfully
           ' and our val variable has been updated.
        Catch ex As FileNotFoundException
           MessageBox.Show("Could not find the specified file.")
        Catch ex As System.IO.IOException
           MessageBox.Show("Could not read from the specified file--check it is valid.")
        End Try
    End If

    ' Our variable val will now contain the value read from the file,
    ' if that whole business was successful. Otherwise, it will
    ' contain the default value of 0 that we set at the top.
End Sub

In real code, you would also make extensive use of Using blocks to handle the automatic cleanup of any object that implements the IDisposable interface in case an exception is thrown. Revising our example above, assuming that the File class I made up implements IDisposable:

Public Sub Main()
    Dim val As Integer = 0    ' 0 is our "default" value

    ' Don't need a Try here, this won't throw an exception.
    ' It will just return an empty string if they canceled.
    Dim fileName As String = AskUserForFileName()

    ' See if they canceled...
    If (fileName <> String.Empty)
        Try
           ' Now we need a Try block, because we're going to do
           ' stuff that might throw an exception.
           Using file As File = OpenFile(fileName)
               ' Execution won't get here if OpenFile() threw an exception, so
               ' at this point, we know that the file was opened successfully,
               ' so we'll try to read our value from it.
               val = ReadDataFromFile(file)

               ' Again, execution won't get here if ReadDataFromFile() threw
               ' an exception, so we know that the data was read out successfully
               ' and our val variable has been updated.
           End Using  ' make sure file always gets closed properly
        Catch ex As FileNotFoundException
           MessageBox.Show("Could not find the specified file.")
        Catch ex As System.IO.IOException
           MessageBox.Show("Could not read from the specified file--check it is valid.")
        End Try
    End If

    ' Our variable val will now contain the value read from the file,
    ' if that whole business was successful. Otherwise, it will
    ' contain the default value of 0 that we set at the top.
End Sub

Upvotes: 1

Related Questions