You should read this article: Rethrowing exceptions and preserving the full call stack trace In short, throw usually preserves the stack trace of the original thrown exception, but only if the exception didn't occur in the current stack frame (i.e. Method). There is a method PreserveStackTrace (shown in that blog article) that you use that preserves the original stack trace like this: try { } catch (Exception ex) { PreserveStackTrace(ex); throw; } But my usual solution is to either simply to not catch and re throw exceptions like this (unless absolutely necessary), or just to always throw new exceptions using the InnerException property to propagate the original exception: try { } catch (Exception ex) { throw new Exception("Error doing foo", ex); }.
Thanks, the link you provided was really useful, and calling directly the InternalPreserveStackTrace allowed me to solve my problem! – Brann Mar 1 at 16:43.
The problem is that Windows is resetting the stack's starting point. The CLR is behaving as expected—this is just a limitation of the host operating system's exception handling support. The problem is that there can only be one stack frame per method call.
You could extract your exception handling routines into a separate "helper" method, which would work around the limitations imposed by Windows's SEH, but I don't think that's necessarily a good idea. The proper way to rethrow an exception without losing the stack information is to throw a new exception and include the original, caught exception as the inner exception. It's difficult to imagine very many cases where you'd really need to do this.
If you're not handling the exception, and simply catching it to rethrow it, you probably shouldn't be catching it in the first place.
– Brann Mar 1 at 9:09 see this question for example stackoverflow. Com/questions/730250/… ; this seems to be in contradiction with your answer – Brann Mar 1 at 9:11 @Brann: Uhh, they're still different. Throw ex resets the stack trace, throw doesn't.
The problem you've set up here is an edge case. You have the exception handlers in the same method, and Windows only supports one stack frame per method call. The difference between throw and throw ex is at the level of the CLR; as explained in my answer, that's working correctly here.
You're just hitting against a limitation of the host operating system. – Cody Gray Mar 1 at 9:11 Ok I get it.So this would work if wasn't in the same method ; right? – Brann Mar 1 at 9:12 @Brann: Yes, if you split the code into a separate helper method, it would "work".
I wouldn't do that just to fix your exception handling routines, though. – Cody Gray Mar 1 at 9:13.
The normal rethrow preserves everything on the stack trace except that if the present method is in the stack trace, the line number will get overwritten. This is annoying behavior. In C# if one needs to do something in the exceptional case but doesn't care what the exception is, one can use the pattern: Boolean ok = False; try { do_something(); ok = True; } finally { if (!ok) // An exception occurred!
Handle_exception(); } There are a number where that pattern is very helpful; the most common would be a function which is supposed to return a new IDisposable. If the function isn't going to return, the disposable object must get cleaned up. Note that any "return" statements within the above "try" block must set ok to true.In vb.
Net, it's possible to use a pattern which is functionally a little nicer, though one spot in the code is a little icky, with the pattern: Dim PendingException As Exception = Nothing; Try Do_Something PendingException = Nothing ' See note Catch Ex As Exception When CopyFirstParameterToSecondAndReturnFalse(Ex, PendingException ) Throw ' Will never execute, since above will return false Finally If PendingException IsNot Nothing Then .. Handle exception EndIf End Try The long-named function should be implemented in the obvious fashion. This pattern has the advantage of making the exception available to the code. While that isn't often needed in handle-but-don't-catch situations, there's one situation where it can be invaluable: if a cleanup routine throws an exception.
Normally, if a cleanup routine throws an exception, any pending exception will be lost. With the above pattern, however, it's possible to wrap the pending exception within the cleanup exception. One interesting note with the above code: it's possible for an exception to reach the "Catch When" and yet for the Try statement to complete normally.
It's really not clear what should happen in that circumstance, but one thing that is clear is that the Finally statement should not act as though an exception is pending. Clearing PendingException will make it so that if an exception vanishes, the code will behave as though it never happened.An alternative would be to wrap and rethrow an exception which is known to have occurred, since that situation almost certainly indicates something wrong with the inner exception-handling code.
My first thought was the same as your first example, but it's very difficult to imagine a case where you have an object that implements IDisposable and you couldn't just wrap the whole thing in a using block. There are several other questions here that demonstrate conclusively there's nothing wrong with returning from inside of a using block. As far as your second example, blech!
It certainly seems "clever", but it's one of those things that's far too clever for one's own good. I can't imagine being forced to maintain code like that. Wrapping it as the inner ex is much clearer.
– Cody Gray Mar 1 at 23:36 @Cody Gray: How does one usefully wrap a constructor in a "using" block? If the object is going to go out of scope without being returned to the caller, it must be Dispose'd, but if the object is going to get returned to the caller, it must not be. A "using" block doesn't provide any assistance with such scenarios.
– supercat Mar 2 at 0:20 @Cody Gray: As for the icky code to capture the pending exception, I wish there were some better language construct, but there isn't. If an area of code that will require cleanup throws an exception, it's not uncommon that the condition that cause the exception will also cause cleanup to fail. It's bad to swallow exceptions from a failed cleanup, but it's also bad to have cleanup code throw a new exception that destroys an earlier one.
Best is for the cleanup to throw an exception with the old exception as an InnerException, but HOW DOES ONE DO THAT without code similar to what I showed? – supercat Mar 2 at 0:24.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.