4

Suppose I have the following construct:

Public Sub SomeMethod()
   Try
      doSomething()
   Catch ex as Exception
      handleException(ex)
   End Try
End Sub

And I would like to write handleException(ex). Suppose my class has different options of handling events:

 Public Enum ExceptionHandlingType
        DisplayInMessageBox 'Display in msgbox
        ThrowToCaller       'Raise the error to the caller routine
        RaiseOnMessageEvent 'e-mail
    End Enum

Below is my attempt at writing "handleException". It seems no matter what I do, if the object was set with Exception mode of "ThrowToCaller" then the stack trace gets all messed up when I use handleException(). How can I just have a clean stack trace generated when the option is "ThrowToCaller" (every other option seems like it is working fine)

Public Sub handleException(ex as Exception)
  Select Case mExceptionHandling
            Case ExceptionHandlingType.DisplayInMessageBox
                MsgBox(ex.Message)
            Case ExceptionHandlingType.ThrowToCaller
                Throw New Exception(ex.Message, ex)
            Case ExceptionHandlingType.RaiseOnMessageEvent
                SendEMailMessage(ex)
        End Select
End Sub
Denis
  • 11,796
  • 16
  • 88
  • 150
  • Take a look at this http://jmcilhinney.blogspot.com/2009/11/defining-and-raising-custom-events.html – dbasnett Jul 05 '11 at 18:51
  • 2
    You should not be creating any such method. You should only be "handling" exceptions that you can actually handle. – John Saunders Jul 05 '11 at 18:52
  • I am thinking maybe I need to go the route of Log4Net and such. They are able to have a "handleException-like" method that does log to a file or popup a message box... but how do you throw it out correctly if you are in a different method? – Denis Jul 05 '11 at 18:58

2 Answers2

2

To retain the stack trace of an exception in a catch block it has to be thrown with the following syntax (in C#, not familiar with VB):

try {
   // some operation ...
} 
catch (Exception ex) {

switch(mExceptionHandling) {

case ExceptionHandlingType.ThrowToCaller: throw;
case ExceptionHandlingType.DisplayInMessageBox: MsgBox(ex.Message); break;
case ExceptionHandlingType.RaiseOnMessageEvent: SendEmailMessage(ex); break;
default: throw;

}

}

Take a look at the exception handling block to get an idea of best practices of exception handling.

EDIT: Take a look at the answers here to find ways to preserve stack trace.

EDIT #2 I think part of the issue here is that this is not the best way to handle exceptions for the use case at hand. From the looks of it, this looks like GUI code due to the message box. The decision to display a message box should be made outside of this particular catch block. One way would be to use AOP to inject a message box handler for certain operations and certain exception types. The catch-rethrow scenario typically applies when you want to log the exception. At this point, you can have an interim solution by extracting the stack trace using reflection, but in the future consider refactoring your exception handling model.

Community
  • 1
  • 1
eulerfx
  • 36,769
  • 7
  • 61
  • 83
  • This is exactly what I had originally in about 200 places in this 1 class (it's a GUI control actually) so I thought maybe I should refactor it to be in 1 place like the "HandleException" method and this is what I am trying to figure out how I could do. – Denis Jul 05 '11 at 18:56
  • 1
    The only easy way I know of preserving the stack trace of an exception without using the throw; syntax in the catch block is to wrap it in a new exception. Take a look here: http://stackoverflow.com/questions/57383/in-c-how-can-i-rethrow-innerexception-without-losing-stack-trace for some discussion. – eulerfx Jul 05 '11 at 19:00
  • I can kind of predict the next comment so I am going to say this is old code that has been around for years and everyone modified it. I am just trying to get the error handling under control instead of having it in 200 places and then if there is a new option, having to modify it in 200 places. – Denis Jul 05 '11 at 19:02
  • I try to wrap it in another exception. See above in my case statement. But the problem is that this wrapping of exception produces the strangest stack trace which doesn't make any sense - it is not sequential because the sequence gets messed up once I enter "handleException" – Denis Jul 05 '11 at 19:03
  • I agree completely with your points above but the code is what it is and of course re-writing this would be ideal including all the exception handling which was mostly converted from old Access code and to use Log4Net but just not an option. – Denis Jul 05 '11 at 19:32
2

Try changing the call to

if (!HandleException(ex)) throw;

and HandleException() to

bool HandleException(Exception ex) {
    bool handled = false;

    if (ex is SomeException) {
        ... handle the exception ...
        handled = true
    }
    return handled;
}

That should do the trick.

Jouke van der Maas
  • 4,117
  • 2
  • 28
  • 35