Catching Exceptions from a Subroutine

Say you have a Sub that calls a second Sub and an exception occurs in the second Sub, which you catch. Then when the second Sub drops out, execution continues with the next line of the first Sub (i.e. the calling Sub). I'm wondering if there is anyway to let the first Sub know that an exception occurred in the second Sub and allow the first Sub to also drop out instead of continuing.

Here is an example in code. You can recreate it by creating a Windows Application and copying the code into the Form1 code.

Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

func1()

End Sub

Private Sub func1()

Try

func2()

' Some how func1 needs to know that func2 had an error so that

' func1 can drop out here, instead of calling the following

' code, which will cause another exception.

Dim test As Integer = 0

test = test / 0

Catch ex As Exception

MsgBox("func1")

Finally

' Ideally funct1 needs to perform its Finally action before

' dropping out.

End Try

End Sub

Private Sub func2()

Try

Dim test As Integer = 0

test = test / 0

Catch ex As Exception

MsgBox("func2")

End Try

End Sub

End Class

I know there are ways that I can hack around this. Such as making the second Sub a Function instead, which returns a Boolean value for success or failure. However, I have functions that need to return other types of values, so this isn't always possible. I could also create an external variable (class scope) that can be set in the second Sub. The first Sub could then check this value and drop out if it indicates that the second Sub failed.

The hacks seem so inelegent, so I'm wondering if there is a better, cleaner way to achieve this Any help is appreciated, thanks.



Answer this question

Catching Exceptions from a Subroutine

  • Yves Dolce

    Why is having a function return a boolean value to indicate success of failure a 'hack'

    Hmmm...personally, I find the use of Boolean return values to indicate success/failure to be a bit of a hack. To me, it goes against the spirit of structured error handling. It just seems too much like what we had to do in the VB6 days. I think that if your .NET method has failed, then it should throw an exception.

    The use of exceptions give programmers a parallel channel by which error information can be returned from a method without having to "pollute" the signature or the return value of the method. For example, if you have a Sub DoSomething, it shouldn't be forced to be a function just to return a Success or Fail flag. When I see a Function, I should be able to assume that the return value contains the material result of that function, not that the Function is really a Sub masquerading as a Function. Subs do something; Functions return something.

    I believe that keeping information about the success or failure of a method outside of the signature or return value of the method makes for a much cleaner overall interface.

    (BTW, I'm not saying that you should never have a Function return a Boolean value; just that the Boolean value should not indicate whether "This function failed to do what it was supposed to do". To me, there's a big difference between a Function that successfully determined a True/False state and a Function that failed. For example, if the IsValid Function has to connect to the database to make the determination, but the database is down, then it should throw an exception, not return False.)

    - Mitchell S. Honnert


  • texag

    Ged wrote:
    I don't know if it's any more elegant (probably not), but instead of the Function/Boolean hack you could put a flag in the Catch Block of Sub2 which is tested when the call returns to Sub1.

    Why is having a function return a boolean value to indicate success of failure a 'hack'



  • Etienne VSTS MVP

    Yes, of course! I completely forgot that you can use a Try...End Try block without the Catch. This works perfectly and does exactly what I want. I was just about to sit down and start implementing one of the other solutions until I read your post Alex.
  • debrucer

    Yes, I agree with what you are saying. As a note about the MsgBox stuff. My error handler only displays them to me. My end user doesn't actually see the error. It is purely for my debugging purposes. The application does in fact handle the exceptions correctly.

    So anyway, anyone have any more opinions on a solution to this problem


  • rajesh_chd

    Another option, if you expect the first function not to continue executing when an exception happens in the second function, but you don't want to handle it twice, would be not to handle it at all in the second function, and have the handling occur only in the first function. You can still have a

    try
    ...
    finally
    ...
    end try

    Statement in the second sub to do any processing you need to clean it up.

    About exceptions In general the way I see it it's a matter of what kind of information you want a function to return: is it supposed to indicate that it failed catastrophically, as in throwing an exception, or is it executing conventionally and returning expected information, whether it's a boolean true/false
    For example, I might design a FileExists to return a boolean to indicate whether a file exists or not, and throw an exception if the path is not accessible.

    One of advantages of using exceptions only for exceptional events, is that when a bug causes an error in your code, you can set the debugger to break on exception throw, hit F5 and get directly to where the error is occuring :)



  • bazmcl

    Yeah, that's what I meant by the class scope variable. Just want to see if anyone has a better solution to the problem before I go down some path like this one.
  • rebelR

    I agree, which is why I believe that changing half of my Subs into Functions just for the purpose of Success/Fail is a hack. Besides, I already have functions that return values, which also require this sort of error handling, so like I said in my OP, this hack isn't always viable.

    I kind of like the idea about throwing another exception after handling it in Sub2, so that Sub1 will catch it and drop out too. However, this means that Sub1 will also perform its error handling for an exception that it doesn't need to handle (as it was handled in Sub2). I have an error handling system that all my exceptions are sent to in the Catch block and it does the work of displaying a MsgBox, etc... Perhaps in this new exception (the one I throw in Sub2, so that Sub1 drops out too), I could set the Message text to something like "ignore" so that the error handler can read this and knows to ignore this exception (i.e. not display a MsgBox to the user). What do you think

    Otherwise I'm left with the flag option. I could create a DidSub2Pass variable in the class scope and set it to true when I enter Sub2. If Sub2 fails in anyway, then I set it to false and Sub1 can check this as soon as Sub2 returns. Then I can just tell Sub2 to return too, knowing that it's Finally code will be called as it is always called before the Sub actually returns. The only disadvantage I can see is if I need to do this for several different Subs, in which case I need to create several of these class scope variables, which could get messy. Do you think this is a better option though, or worse

    Or is there yet another option that someone knows, which I haven't seen


  • DMukaiwa

    Good answers!

    But considering the issue of discussion here - and the problems, specifically, aren't we refering to 'structured' exception handling Sure, it has a structure, but the fact that it's so complicated to resolve such a simple scenario with exception handling demonstrates that perhaps structured exception handling isn't the panacea that it's often argued.

    However, my bias is probably showing - I'm certainly from a VB6 (and earlier) background so I have a liking for inline exception handling - I also consider it easier to read, but that's my preference.

    I'll also contend, though that there is a huge difference between a failure and an error. All too often I've jammed into people that they need to have error handling of some kind to find that programs still crash: on inspection [of the code], every cause of error is handled - programmatically, sure, but nothing is done about it!

    Consider a file opening routine: perhaps it's encapsulated in a function called 'OpenMyFile'. There obviously has to be some kind of error handling in that routine because soooo many things can go wrong. However, whatever function uses that routine doesn't need to know about the error - it doesn't care. It wants a file to do stuff with, and there are only two outcomes: I either have the file or I don't.

    I'm probably flying off on a tangent, here (and a rant), but have seen too much code with 'correctly' structured error handling which, quite honestly is absolute rubbish spaghetti: how ironic.

    Oh, since I'm on a rant: Message Boxes are only for debugging: users don't read message boxes, and if they did, they wouldn't understand it, anyway. Message boxes are only there so the programmer doesn't have to make a decision, and when the program breaks, because the user pushed the wrong button, it's not the programmers fault.

    Sorry , not having a go at anyone in particular - I'm just fed up of stupid message boxes and darned stupid programmers that think it's fine that they've 'handle the error' - but the darned program has crashed anyway, so what good is it!

    I'll try and calm down, now . The art of programming is knowing when to use the exception handling. If you treat an Exception a 'all hell has broken lose' in my application, you need to regain control as quickly as possible: reduce the damage (exceptions).



  • vishybhai

    Ah, Ok. Just wondering....

  • steve8man

    Not my definition - I was just responding to the original poster's comment of:-

    "I know there are ways that I can hack around this"

    I'd be perfectly happy to create a function with a boolean return value in very many situations.


  • roger42

    I don't know if it's any more elegant (probably not), but instead of the Function/Boolean hack you could put a flag in the Catch Block of Sub2 which is tested when the call returns to Sub1.
  • veeta

    Glad to be of help :)

  • nagarajuch

    Or perhaps in Sub2 after the messagebox, just add a new statement "Throw" (or is it "Throw ex", I forget), which will throw the original exception back to the caller. Of course, removing the catch block entirely in Sub2 will also allow the exception to bubble up to Sub1, but then you will not have a messagebox and you will not have an opportunity in Sub2 to augment or enhance the exception at the place that it occurs.

    The same comments can be applied to Sub1.

    Hope this helps.


  • Catching Exceptions from a Subroutine