1

I seen this in legacy code. What, if any, is the purpose of a single Throw within a Catch?

       Try
           'Some Oracle access statement
       Catch err As OracleClient.OracleException
            Throw
       Finally
          'Do something
       End Try

Is the outcome the same as if the original error was not caught? Would you use a Throw statement w/o parameters to re-throw the original error, typically after performing some action first?

Chad
  • 23,658
  • 51
  • 191
  • 321

7 Answers7

4

I've often used that pattern when debugging; I'll set a breakpoint on the throw statement so I can inspect err. Not sure if there's another good reason to do this though.

James J
  • 6,428
  • 6
  • 35
  • 45
3

Many people think it's a no-op, but it's not. If you have this program:

Module Module1
    Function Filter() As Boolean
        Console.WriteLine("1")
        Return True
    End Function

    Sub Thrower()
        Try
            Throw New Exception("x")
        Finally
            Console.WriteLine("3")
        End Try
    End Sub

    Sub NoCatch()
        Try
            Thrower()
        Finally
            Console.WriteLine("2")
        End Try
    End Sub

    Sub WithCatch()
        Try
            Thrower()
        Catch ex As Exception
            Throw
        Finally
            Console.WriteLine("2")
        End Try
    End Sub

    Sub Caller(ByVal method As Action)
        Try
            method()
        Catch ex As Exception When Filter()
        End Try
    End Sub

    Sub Main()
        Console.WriteLine("No Catch")
        Caller(AddressOf NoCatch)
        Console.WriteLine("With Catch")
        Caller(AddressOf WithCatch)
    End Sub
End Module

The output is

No Catch
1
3
2
With Catch
3
1
2

Edit: One scenario when this actually matters this: The Thrower and NoCatch functions are in the same assembly, which is thrusted. The Caller method is not trusted and malicious. Now imagine that the Thrower method uses WindowsIdentity to impersonate another user, which the untrusted assembly is not allowed to do. It then relies on a using block (= try/finally) to unimpersonate the user, but it throws an exception. This would mean that the malicious assembly runs as the impersonated user during the execution of the Filter method. Perhaps this will also work if asserting permissions, but I'm not sure.

erikkallen
  • 33,800
  • 13
  • 85
  • 120
  • Interesting... but concretely would that change anything? In what case would the order in which the finally clauses are called be important? – Meta-Knight Sep 22 '09 at 18:15
  • It obviously matter if you have a program whose sole spec is to write the numbers 1, 3, 2 to the console (in that order) and try to solve it with the code above :) – erikkallen Sep 22 '09 at 19:33
  • Another interesting thing to note is that filters may in some cases allow one to log exceptions which end up getting overwritten without ever being caught. `P1` [in vb.net] calls `P2` within `Catch ZooException When ZooFilter()`, which calls `P3` within a `try/catch MooException` block. `P3` calls `P4` within a `try/finally` block whose `finally` clause throws `MooException`, and `P4` throws `ZooException`. Even if the filter in `P1` sees the `ZooException` and decides to catch it, the exception could disappear before it gets that far. – supercat Oct 14 '13 at 17:01
1

This would be to re-throw the same error. It would allow you to do work in the Finally block while re throwing the error to the caller

EDIT

Apparently the Exception bubbles up without the catch and re-throw so it is not needed. I stand corrected.

Gratzy
  • 9,164
  • 4
  • 30
  • 45
  • Agreed. It allows for the exception to happen but the finally code allows you to do something like close a connection or roll back the transaction before passing the exception back to the calling process. – Bomlin Sep 22 '09 at 17:16
  • 1
    This answer implies that you are required to have a catch in order to have a finally, but that isn't true. :) – jsight Sep 22 '09 at 17:19
  • I was not imply you needed the catch to have the finally block, I thought you would need the catch and re-throw for the exception to bubble up. I was not aware it would bubble up anyway. – Gratzy Sep 22 '09 at 17:22
1

That does nothing. Throw as there is correct.

You could delete the catch but you'd want to leave the try if there is more than a comment in the Finally.

dove
  • 20,469
  • 14
  • 82
  • 108
1

It catches the error then throws it again. I don't see the point because you can do Try...Finally without a Catch clause...

jenningj has a good point though, it could have been used to inspect the error with a breakpoint, but it should not appear in production code.

Meta-Knight
  • 17,626
  • 1
  • 48
  • 58
1

The main reason to use throw without a parameter is that it will preserve the original stacktrace.

Also instead on placing a breakpoint on the throw statement, you could have changed your VS Settings to break on oracle exceptions, thats much easier then adding breakpoints all over the place

Heiko Hatzfeld
  • 3,197
  • 18
  • 15
1

It looks like it is being used to bubble the error up. While one would normally put more in the catch statement than just throw (i.e. logging, alerts, etc.) in this case it is allowing a finally statement to be used to do some cleanup then bubbling the error up to the next level. Without the try/catch how would this cleanup code be written at this scope? As someone mentioned already the throw syntax (without ex) is preserving the stack trace.

Jason Irwin
  • 1,985
  • 2
  • 29
  • 42