1

Suppose I have the following construct:

Try 
  Dim f As FileInfo = Nothing
  f.Delete()

  ... some other stuff...
Catch ex as Exception
   Throw
End Try

In this simple example f.Delete would throw a NullReferenceException.

  1. Why would the problem line in the StackTrace of this exception point to the Throw statement and NOT to the line f.Delete()?

  2. How can I keep the Try/Catch but have the CORRECT stack trace pointing to f.Delete() as the source of the problem?

Denis
  • 11,796
  • 16
  • 88
  • 150
  • 1
    Don't re-throw the exception – Shar1er80 Jun 11 '15 at 20:36
  • So in VB.NET a lot of people catch the exception within the method (leave aside whether this is good or bad practice) because they like to do run-time debugging and if an exception is thrown it stays within the function/sub. The way they generally achieve this is with the construct above but it causes problems when exceptions happen deep in code and I can't figure out what line is involved. So short answer is that they want to keep this construct but make it work right. – Denis Jun 11 '15 at 20:38
  • If you only want the one `Try..Catch` block, you can always use flags to determine where the error occurred. For example set an integer to 1 after the the `f.Delete()` to signify success. Then in your `Catch`, you can test the integer to see whether or not your code got past the `f.Delete()` – DeanOC Jun 11 '15 at 21:06

2 Answers2

2

1. Why would the problem line in the StackTrace of this exception point to the Throw statement and NOT to the line f.Delete()?

It depends which stack trace you're looking at: that generated by the rethrow (the Throw inside your catch block), or that by first exception being caught?

Set a breakpoint on the Catch ex As Exception line and inspect ex with the debugger; you will see a stack trace pointing to f.Delete().

Throw means "re-throw", i.e. the original stack trace will be preserved... However, you don't get two entries in the stack trace for the same method invocation: if the exception gets re-thrown in the same method that originally caused the exception, the stack trace will only contain an entry pointing to the final re-throw.

2. How can I keep the Try/Catch but have the CORRECT stack trace pointing to f.Delete() as the source of the problem?

  1. Remember that a re-throw basically means, "I was wrong, I don't know how to handle this exception after all." So instead of re-throwing, you might be able to use an exception filter (Catch … When <boolean-expression>) to decide whether you actually can handle the exception before you catch it. If you can determine that before catching it, a rethrow should become unnecessary, and the stack trace will not get modified.

  2. Put the f.Delete()in a different method. That way, it gets its own stack frame / line in the stack trace and won't get overwritten by a re-Throw.

(Or, simply don't catch the exception just to rethrow it.)

Denis
  • 11,796
  • 16
  • 88
  • 150
stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
  • I thought that the behavior you are explaining is what happens with `throw ex`. This is why we use `throw` to supposedly have the correct behavior. I thought the difference between `throw` and `throw ex` is that `throw` will keep the stacktrace as originally thrown and `throw ex` will show the stacktrace from the line where it was executed. – Denis Jun 11 '15 at 20:34
  • @Denis: I've rewritten my answer. Should be more helpful now. – stakx - no longer contributing Jun 11 '15 at 21:01
  • So I understand it now after doing some tests. No matter whether you do `throw` or `throw ex` the result would be the same here. Both would overwrite the stack frame for this method the same way. – Denis Jun 11 '15 at 21:27
  • @Denis: There might be no difference in your specific case. (See also [this answer and the comments to it](http://stackoverflow.com/a/730255/240733), and [this blog post](http://geekswithblogs.net/sdorman/archive/2007/08/20/Difference-between-quotthrowquot-and-quotthrow-exquot-in-.NET.aspx).) However I would still say that in principle, `Throw` and `Throw ex` differ in meaning / intent. Do a re-throw if you decide you cannot handle an exception, and therefore want to preserve the original stack trace (as far as possible). Do a `Throw ex` to have an exception point at the "new" throw location. – stakx - no longer contributing Jun 12 '15 at 07:22
0

I guess this could also work to give the right exception (at least in the "inner" exception):

Try 
  Dim f As FileInfo = Nothing
  f.Delete()

  ... some other stuff...
Catch ex as Exception
   Throw New Exception("Failed in Method X", ex)
End Try
Denis
  • 11,796
  • 16
  • 88
  • 150