locked
Don't Handle An Exception You're Not Prepared To Deal With RRS feed

  • General discussion

  • I've posted this many times and will again - since it's come up in a thread, don't handle an exception you're not prepared to deal with!

    A short three-minute video is on my site here and I hope it might help some in the future.


    Please call me Frank :)

    Sunday, September 15, 2013 9:50 PM

All replies

  • why not create a TechNet wiki article + enter it in the guru competition?

    http://social.msdn.microsoft.com/Forums/vstudio/en-US/5b9b02d9-ec10-43ab-aa86-7fa2b4ea94e0/you-could-be-septembers-technet-guru-turbo-charge-your-cv-with-awards-and-interviews-get-noticed


    thanks for any help


    Ahh -- not my style Paul, but thanks for that. :)

    Please call me Frank :)

    Sunday, September 15, 2013 10:20 PM
  • Frank, When an unexpected exception occurs, is there anyway to change the text "Unhandled Exception Occurred"?  I have a couple of users at each client that call and say, why didn't you handle this error. Of course, those users are very creative at creating errors.

    The difference between genius and stupidity is that genius has its limits.

    Monday, September 16, 2013 1:01 AM
  • When an unexpected exception occurs, is there anyway to change the text "Unhandled Exception Occurred"?

    Is this the sort of thing you're after: Global Exception Handler (WinForms)?

    --
    Andrew

    Monday, September 16, 2013 8:14 AM
  • Thanks for sharing Frank. I always believe that other than uncatchable OS type of errors we as developers should be using the unhandled expection handler under My.Namespace. I have a simple example in the link below.

    http://code.msdn.microsoft.com/Dealing-with-unhandled-9b933818

    Our team version sends email alerts and writes to xml log files that can be viewed in a special browser app.

    Many times users will not report what I call pesky errors that cause an app to fail. A common one for us is when a user account is not setup correctly and the app can not find My Documents (or Documents etc) folder and the fix is a tech from support to correct the problem. Since we get email alerts we tell the support team of the problem, they zero in on the user since the code for unhandled exceptions records this and the user is fix via remote session. Second issue that gets resolved the same way is wrong version of a data driver.


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem.

    Monday, September 16, 2013 10:13 AM
  • When an unexpected exception occurs, is there anyway to change the text "Unhandled Exception Occurred"?

    Is this the sort of thing you're after: Global Exception Handler (WinForms)?

    --
    Andrew

    I'll toss in this question:

    Is there ever a time when it's appropriate to intentionally leave the Catch empty?

    My answer: Yes.

    If you can't do anything about it, then logging it might be appropriate, but with some - there's no point even in doing that.

    Here's an example: Let's say that you have a method built which processes images - for instance, maybe it's creating a bunch of thumbnail images or who knows what.

    Everyone who's done that knows that sometimes the process will fail - GDI+ exception or OOM or ... something.

    If you put a Try/Catch in that method, what happens when you're processing 1000 images and the exception occurs on the second one?

    It fails, it exits the method, and that's that. You only have one thumbnail image done. But just because one failed - why condemn all of the rest of them?

    A better way would be to have yet another method do the actual processing based on a parameter passed in (like the path to the image file). Have the Try/Catch in there and if it fails, simply return Nothing rather than the thumbnail image.

    Now if it fails on that second one, the rest are still processed; you're only left with one that didn't make it through.

    *****

    Another case might be if you're trying to delete a folder when the form is closing. So you put a Try/Catch in place. Most of the time it succeeds but there's a possibility (for whatever reason) that a file in that folder is locked and the method will fail.

    You can't do anything about it - your user can't do anything about it - so why show a message or log it or anything? I see no point in it.

    Your thoughts (everyone)?


    Please call me Frank :)

    Monday, September 16, 2013 1:57 PM
  • Your thoughts (everyone)?

    I agree, and I don't agree. :-)

    I agree that there are some cases where it can be empty.
    I don't agree because in those cases at least a comment should be added like "intentionally empty", or "can be ingored because...".

    So, actually I agree.

    To add another example: When calling control.BeginInvoke. No matter how hard you try, this is the only reliable way to handle the case that the control, usually a Form, has been destroyed.


    Armin


    Monday, September 16, 2013 2:06 PM
  • Your thoughts (everyone)?

    I agree, and I don't agree. :-)

    I agree that there are some cases where it can be empty.
    I don't agree because in those cases at least a comment should be added like "intentionally empty", or "can be ingored because...".

    So, actually I agree.

    To add another example: When calling control.BeginInvoke. No matter how hard you try, this is the only reliable way to handle the case that the control, usually a Form, has been destroyed.


    Armin



    Well that's true about the comment. I usually type in "Nothing we can do about it..." or something like that.

    Please call me Frank :)

    Monday, September 16, 2013 2:17 PM
  • Here are some samples of working with the unhandled exception handler I spoke of in my first post which I could not post before as I was home and the work version is different than my home version.

    Figure 1 shows what we use which for some may think "why show information the user does not understand?" This was a decision made by the entire team. Now in figure two we simply give them a message that is easy to understand (just made this up and could be whatever you think is good).

    Also note in Figure two the main form (created in Framework 2, back when we first started using this) was setup to show how some common errors would be trapped except of course for Fail Fast. Edit: I left a word out in the dialog, bad programmer, bad, bad programmer :-)

    Also note, although it may not be easy for novice developers to setup code contracts is another way to prevent some exceptions at run time. And a no brainer, rigorous testing done by testers with a test plan other than the developer which is what we have been doing for years. It takes a good deal of resources but when dealing with mission critical apps that are up 24-7 it pays off in the end.

    Figure 1

    Figure 2


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem.


    Monday, September 16, 2013 2:43 PM
  • Kev,

    I like that!

    Good thinking!


    Please call me Frank :)

    Monday, September 16, 2013 2:48 PM
  • Kev,

    I like that!

    Good thinking!


    Please call me Frank :)

    Frank,

    One of my pet peeves is for an application in our shop to crash from a bug in the program except for un-trappable issues, as to implement unhandled exceptions is to simply add a reference to a class library compiled DLL and add in a xml configuration file.


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem.

    Monday, September 16, 2013 2:58 PM
  • I agree 100% with the "don't catch it if you don't know what to do with it". But don't stop there! In another thread I was defending the use of a debugger in production environments, for exactly the same reason, to catch and solve errors quickly, see here: http://social.msdn.microsoft.com/Forums/vstudio/en-US/53b799e1-628f-48a5-b282-606d0d3acbab/debugger-nops#bfd0912b-14ec-47c4-9cb6-72bbc9ecadf2.

    In automation (PLC) environments this is common practice, they call it "going online". It's so weird so few IT people even consider the possibility and seem to reject it...

    One problem of course is VS express clearly states 'for evaluation purposes only', so I don't feel to comfy with the 'run it in VS express' approach. What we really need imo is a full featured stand-alone debugger for production environments (or maybe a remote debugger), it's there where most unexpected errors will occur.



    • Edited by exstud Monday, September 16, 2013 3:49 PM
    Monday, September 16, 2013 3:00 PM
  • Here's an old (but still valid) article about Exception Handling:

    http://www.codeproject.com/Articles/154121/Using-Try-Catch-Finally


    Please call me Frank :)

    Monday, September 16, 2013 3:34 PM
  • Is there ever a time when it's appropriate to intentionally leave the Catch empty?

    Definitely! Another example: if the last gasp of the program involves sending an email log of the error and that fails (say, the mail server is down), there isn't really anything you can do about it apart from perhaps change the message shown to the user to indicate that it couldn't send the email and please would they contact you.

    Of course, you would be setting an emailFailed flag in the Catch in that circumstance, so it wouldn't be totally empty.

    For your last example, you could put an entry in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce for a batch file to try to delete the offending items on the next boot.

    --
    Andrew

    Monday, September 16, 2013 6:06 PM
  • To me, everything should either "Pass" or "Crash", 

         It is never to a method to decide what to do with an exception, ... it is to the user of the method. 

         So, if it cannot work, ...  Throw 

         And  bubble up your exceptions until you reach the point where there is a logical way to deal with it or until you reach the GUI.

         Only when the GUI is reached should you pop something to let the user know.

    As much as possible, use this pattern when calling something that may fail, testing for every possible reason to fail

            If NecessaryCondition_1 Then
                If NecessaryCondition_2 Then
                    If NecessaryCondition_3 Then
    
                        'Safely Call the method
    
                    Else
                        Throw New AppropriateException_3("Message [Code #]")
                    End If
                Else
                    Throw New AppropriateException_2("Message [Code #]")
                End If
            Else
                Throw New AppropriateException_1("Message [Code #]")
            End If

         Only use Try/Catch when it is impossible to check for all the conditions. -- Try/Catch is slow and too often hide the real problem

        Throw exceptions that are relevant to the problem. Dont hesitate to implement a custom exception if no existing exception are

        All Your exceptions should have a code attached to it, and if the exception bubbles all the way up to the user, the code should be show to the user. So if he call you, he can tell you the code number and you know exactly where in the code the exception come from

        Use the UnhandleException event. At least, if you scewed up, you will be able to show something nice to the user, and also it can show some info that will be helpfull for you to fix the problem


    • Edited by Crazypennie Monday, September 16, 2013 7:16 PM 123654
    Monday, September 16, 2013 7:14 PM
  • Crazy,

    Thanks for your feedback. :)


    Please call me Frank :)

    Monday, September 16, 2013 7:17 PM
  • @Crazy

    Throwing custom exceptions for ordinary validation is imo a real bad idea, and catching them would be even worse (you'd have to look for the line location).

    Why not have a return parameter to indicate success/failure like in old c++? A return parameter would not only be faster, it would work in just about any procedural language, independent of exception implementation...


    • Edited by exstud Monday, September 16, 2013 7:47 PM
    Monday, September 16, 2013 7:46 PM
  • Throwing custom exceptions for ordinary validation is imo a real bad idea...

    I guess that's a matter of perspective. When I write a class, in the constructor I'll very typically check for various things and if they're not what they're supposed to be, I'll throw an exception.

    In my view, it's up to the consumer (the calling code) to handle that exception.


    Please call me Frank :)

    Monday, September 16, 2013 7:58 PM
  • I'd have to disagree, instead of putting your logic inside the constructor you could have an Init function, or have a property to indicate success/failure.

    I like to keep my constructors as empty as possible, maybe for just that reason.

    Monday, September 16, 2013 8:10 PM
  • I'd have to disagree, instead of putting your logic inside the constructor you could have an Init function, or have a property to indicate success/failure.

    I like to keep my constructors as empty as possible, maybe for just that reason.

    Touché

    :)


    Please call me Frank :)

    Monday, September 16, 2013 8:13 PM
  • I'd have to disagree, instead of putting your logic inside the constructor you could have an Init function, or have a property to indicate success/failure.

    I like to keep my constructors as empty as possible, maybe for just that reason.

    You're not talking about "Init" is an instance member? This would make constructors useless as they guarantee a consistent object right after construction.

    EDIT:

    Regarding exceptions: I agree with you that functions should pass results as return values whenever possible. But this doesn't apply always. If the caller passed Nothing and this is invalid, an ArgumentNullException must be raised. Returning it via function return value wouldn't make sense as the programmer would then check at runtime if he passed a wrong argument at the call. He should better correct the call instead of validating the call afterwards.


    Armin

    Monday, September 16, 2013 8:20 PM
  • You're not talking about "Init" is an instance member? This would make constructors useless as they guarantee a consistent object right after construction.

    I assumed he meant a private sub ... no?


    Please call me Frank :)

    Monday, September 16, 2013 8:21 PM
  • @Crazy

    Throwing custom exceptions for ordinary validation is imo a real bad idea, and catching them would be even worse (you'd have to look for the line location).

    Why not have a return parameter to indicate success/failure like in old c++? A return parameter would not only be faster, it would work in just about any procedural language, independent of exception implementation...


    Point 1)

    No, to me, this is bad,  very bad.

      - if your function returns false then what?

        Something when bad in the method, ... What, you dont know therefore: 

     1) the parameter that was pass byRef is in an unknow state, You can have exactly no trust in the value of the parameter.

     2) The problem is hidden. 


      If it makes sens to do validation from inside a class, use this pattern instead of the C++ pattern

           If MyClass.CanDoThis(Value) then
              SomeValue = MyClass.DoThis(Value)
           End If

    --------------------------------

    Point 2)

       Would it make sens for a function in the framework to hide an exception?, .. to handle an exception a way that may not suit your logic?... to pop a message to the user?

    No, you want your function, wich is the caller of the function, to be informed of the reason of the exception and handle it the way it should be done

    So why if the the class was written by you or someone in your team should it be different. 

    Hiding an exception or handling an exception out of the context of the logic of the algorithm is the worst thing you can do.

    If you work this way, here what will happen,... The User will call you saying that something crashed ... and you will be looking at 100,000 lines of code trying to figure out what was wrong in whatever called the method.

    May be is it a bit more work to trace back down what caused the exception, but it will let you pin point all the state of all the variables that have lead to call the function that failled.




    • Edited by Crazypennie Monday, September 16, 2013 8:40 PM 123465
    Monday, September 16, 2013 8:32 PM
  • Point 1)

    No, to me, this is bad, very bad.

      - if your function returns false then what?

        Something when bad in the method, ... What, you dont know therefore: 

     1) the parameter that was pass byRef is in an unknow state, You can have exactly no trust in the value of the parameter.

     2) The problem is hidden.

    But isn't that the way the TryParse methods behave? If the parse fails, the parameter is still in a defined state.

    --
    Andrew

    Monday, September 16, 2013 8:48 PM
  • But isn't that the way the TryParse methods behave? If the parse fails, the parameter is still in a defined state.

    TryParse does not expect that it's always parsable.

    Armin

    • Edited by Armin Zingler Monday, September 16, 2013 8:55 PM +always
    Monday, September 16, 2013 8:55 PM
  • Point 1)

    No, to me, this is bad, very bad.

      - if your function returns false then what?

        Something when bad in the method, ... What, you dont know therefore: 

     1) the parameter that was pass byRef is in an unknow state, You can have exactly no trust in the value of the parameter.

     2) The problem is hidden.

    But isn't that the way the TryParse methods behave? If the parse fails, the parameter is still in a defined state.

    --
    Andrew

    Not at all.

    With TryXXX() you know that the byref parameter is still the value you passed in when the method returns false because that is the expressed behavior of the method.  There was no exception, per-say, so the method knows what state to leave the parameter in.

    But with an outright exception, you have no idea what state the parameter is in.  Maybe the method started to work with it and made some changes before crashing... or maybe it didn't even get to the part where it uses the argument when it crashed.

    Now granted, a C method would return an integer and the value of this integer could indicate to us at what stage within the method the exception occurred.  But we aren't using C... we are using VB.Net.  And in VB.Net we throw and bubble exceptions just like CrazyPennie described.

    At the end of the day, the developer can do anything the language will allow.  And that gives a lot of choices in most cases.  However, if you want your code to play nicely with others, it is best to follow the same patterns and practices as everyone else.  For instance, a class whose constructor can throw an exception may not play well with other code.  The common expectation these days for an object whose construction is questionable is to use a Factory pattern.  The object itself would still have an empty constructor, and then factory methods would be used to create usable instances.  These factory methods are welcome to throw exceptions when the parameter values lead to an invalid object instance.

    Do you have to follow these kinds of patterns and practices?  Of course not.  Should you follow them? Probably.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Monday, September 16, 2013 8:57 PM
  • But isn't that the way the TryParse methods behave? If the parse fails, the parameter is still in a defined state.

    TryParse does not expect that it's always parsable.

    Armin

    ...but TryParse (or TryCast) returns two things: The value and a boolean.

    The only way I know to do that would be to return an instance of a class. How do they do it?


    Please call me Frank :)

    Monday, September 16, 2013 8:58 PM
  • But isn't that the way the TryParse methods behave? If the parse fails, the parameter is still in a defined state.

    TryParse does not expect that it's always parsable.

    Armin

    ...but TryParse (or TryCast) returns two things: The value and a boolean.

    The only way I know to do that would be to return an instance of a class. How do they do it?


    Please call me Frank :)

    They return one thing: a Boolean.

    They each set the value of a ByRef argument, if they succeed.  They do nothing with the argument if they fail.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Monday, September 16, 2013 9:04 PM
  • Reed,

    Thanks for your input.

    This has certainly turned into an interesting discussion (for me at least).


    Please call me Frank :)

    Monday, September 16, 2013 9:04 PM
  • For instance, a class whose constructor can throw an exception may not play well with other code.  The common expectation these days for an object whose construction is questionable is to use a Factory pattern.  The object itself would still have an empty constructor, and then factory methods would be used to create usable instances.  These factory methods are welcome to throw exceptions when the parameter values lead to an invalid object instance.


    I disagree. Usually a exception in a constructor is a wrong argument (e.g. Nothing). That shouldn't be returned by a factory function (as explained in my previous post). I mainly use factory functions because, inside the constructor, it's invalid to write anything before the call to MyBase.New.

    (wow, still cool editor here...  I don't know how long I will stay here this time.^^)


    Armin

    Monday, September 16, 2013 9:11 PM
  • They return one thing: a Boolean.

    They each set the value of a ByRef argument, if they succeed.  They do nothing with the argument if they fail.

    This makes no sense to me - but that's not much of a surprise really. ;-)

    Dim test As Integer = 0

    If Integer.TryParse(TextBox1.Text, test) Then
        ' Do something
    Else
        ' Do something else
    End If

    ... so obviously it returns a boolean - what then casts the value of the text in the TextBox to the variable "test"?


    Please call me Frank :)

    Monday, September 16, 2013 9:11 PM
  • TryParse does not expect that it's always parsable.


    Armin

    ...but TryParse (or TryCast) returns two things: The value and a boolean.

    The only way I know to do that would be to return an instance of a class. How do they do it?

    I misunderstood. Just ignore that post of mine.

    Armin

    Monday, September 16, 2013 9:15 PM
  • Reed,

    In the following:

    Option Strict On Option Explicit On Public Class ExampleData Private _name As String = "--" Private _city As String = "--" Private _state As String = "--" Private _zipCode As String = "--" Public Sub New() End Sub Public Sub New(ByVal name As String, _ ByVal city As String, _ ByVal state As String, _ ByVal zipCode As String) If name.Trim = "" Then Throw New Exception("The name is a required field.") ElseIf city.Trim = "" Then Throw New Exception("The city is a required field.") ElseIf state.Trim = "" Then Throw New Exception("The state is a required field.") ElseIf zipCode.Trim = "" Then Throw New Exception("The zip code is a required field.") Else _name = name _city = city _state = state _zipCode = zipCode End If End Sub Public Property Name() As String Get Return _name End Get Set(ByVal value As String) _name = value End Set End Property Public Property City() As String Get Return _city End Get Set(ByVal value As String) _city = value End Set End Property Public Property State() As String Get Return _state End Get Set(ByVal value As String) _state = value End Set End Property Public Property ZipCode() As String Get Return _zipCode End Get Set(ByVal value As String) _zipCode = value End Set End Property End Class


    ...why is that "not playing nicely"?

    I'm not being a smarta-- here, I'm serious. I want to learn.

    Thanks


    Please call me Frank :)

    Monday, September 16, 2013 9:18 PM
  • Is there ever a time when it's appropriate to intentionally leave the Catch empty?

    My answer: Yes.

    Here's an example: Let's say that you have a method built which processes images - for instance, maybe it's creating a bunch of thumbnail images or who knows what.

    Everyone who's done that knows that sometimes the process will fail - GDI+ exception or OOM or ... something.

    If you put a Try/Catch in that method, what happens when you're processing 1000 images and the exception occurs on the second one?

    It fails, it exits the method, and that's that. You only have one thumbnail image done. But just because one failed - why condemn all of the rest of them?


    I would say, in your example, that the Try Catch is not granular enough.  In other words, the try catch should not surround the code in the method that processes 1000 files, it should surround the code that processes a single file.  If that single file fails, you log it or do whatever, but the outer loop will continue.

    Public Sub MethodThatProcesses1000Files()
        Try
            'Whatever code here to populate the list of files
            ' or other code
            For Each file In ListOfFiles
                processFile(file)
            Next
        Catch Ex As Exception
            'Exceptions that occur here are not from an
            ' individual file.  Most likely we cannont
            'continue processing
        End Try
    End Sub
    
    Public Sub processFile(string filename)
        Try
            'Code to process a single file
        Catch Ex As Exception
            'At least log the exception here
        End Try
    End Sub

    With code similar to this, a single file will not halt the entire program.  It can continue to process the remaining files.

    I would never leave a catch block totally empty.  At the very least, log something somewhere.

    P. S.  Why does this forum software insist on changing the font size if I delete something or try to quote something?  Other forum sites work well, why can't Microsoft get this right?  Arrgh!!


    • Edited by Chris Dunaway Monday, September 16, 2013 9:23 PM typo
    Monday, September 16, 2013 9:22 PM

  • But isn't that the way the TryParse methods behave? If the parse fails, the parameter is still in a defined state.

    --
    Andrew

      The parameter is in the state that Microsoft is telling you that it would be, ... Here you can only trust Microsoft that there will never be any exception inside the method.

      But this doesn't mean that you should use this pattern, ... unless you never make any errors and you can say for sure that your method will never have any exception

      Personnally, I am not bright enough to ever say that for sure about the code I do. (The only thing that I am bright enough to say, is that it can  be something somewhere that will happen and that I will not have thought about. So, I make my code in function of that)


    Being too carefull cost nothing ... Having your client calling you because the application crashes is very expensive, for your wallet and for your reputation
    • Edited by Crazypennie Monday, September 16, 2013 9:30 PM 123564
    Monday, September 16, 2013 9:24 PM
  • Chris,

    Yes that's what I meant - logging it in that case (so that you can show the user why he's one short on thumbnails) has merit, but sometimes it's of no value at all.

    In my second example, he/she can't do anything with it, you can't do anything with it, if it's not destructive then leave it be and catch it (pardon the pun) the next time the program is run.

    Thanks for your input. :)


    Please call me Frank :)

    Monday, September 16, 2013 9:27 PM
  • They return one thing: a Boolean.

    They each set the value of a ByRef argument, if they succeed.  They do nothing with the argument if they fail.

    This makes no sense to me - but that's not much of a surprise really. ;-)

    Dim test As Integer = 0

    If Integer.TryParse(TextBox1.Text, test) Then
        ' Do something
    Else
        ' Do something else
    End If

    ... so obviously it returns a boolean - what then casts the value of the text in the TextBox to the variable "test"?


    Please call me Frank :)

    I think the point was that 'test' remains unchanged if retval=false.

    My 2c:
    There is no standard for this. One should read the documentation of the function whether the ByRef value could have been altered in whichever situation. We shouldn't forget that there are not always only to results, True and False.

    I, the author of the function, do not guarantee that a ByRef remains unchanged. Why? If the caller sees from the function return value that the argument does not contain a meaningful value, he has no reason to access it after the call anyway. The caller has to assume the value to be overwritten anyhow. You, the author of the function, only has to watch out for disposable objects that have to be disposed before returning in case of the object not being required anymore.


    Armin

    Monday, September 16, 2013 9:27 PM
  • I think the point was that 'test' remains unchanged if retval=false.

    What?!?

    That's simply not so!

    If the test fails, the value that it was cast to (test in my example) will be zero. I just happened to have set it to that in the example, but you can set it to minus a million and if it fails, it's zero; otherwise it's the value of whatever was in the TextBox.


    Please call me Frank :)

    ***** EDIT *****

    I should have said that it's the value of the integer that was cast FROM the text in the TextBox

    • Edited by Frank L. Smith Monday, September 16, 2013 9:32 PM ...stupidity
    Monday, September 16, 2013 9:31 PM
  • According to MSDN:

    "When this method returns, contains the 32-bit signed integer value equivalent of the number contained in s, if the conversion succeeded, or zero if the conversion failed."


    Please call me Frank :)

    Monday, September 16, 2013 9:41 PM
  • I see only three reasons for SEH:
    • The only place to catch own programming errors is in every thread's main procedure surrounding the whole code in it. For visual feedback and/or logging.
    • Whenever there's something to close or dispose because we need a finally block that does this.
    • Whenever you expect that something can go wrong and trying is the only way to find out if it works, like disk IO.

    Any other reason?


    Armin

    Monday, September 16, 2013 9:46 PM
  • According to MSDN:

    "When this method returns, contains the 32-bit signed integer value equivalent of the number contained in s, if the conversion succeeded, or zero if the conversion failed."


    Please call me Frank :)

    Ok my mistake.  They set the argument to 0 if they fail.

    Six-of-one, half-a-dozen of the other... you still know what state the variable will be in after the method call returns.  The point is that the behavior is defined by the method.  Nothing was left to chance as it would be if an exception occurred while the TryPare was executing.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Monday, September 16, 2013 9:47 PM
  • According to MSDN:

    "When this method returns, contains the 32-bit signed integer value equivalent of the number contained in s, if the conversion succeeded, or zero if the conversion failed."


    Please call me Frank :)

    Aaaaah, I knew this! Didn't I say it's written in the documentation a couple of posts ago? Sooorry!! Shame on me...


    Armin

    Monday, September 16, 2013 9:48 PM
  • Reed and Armin,

    Read the whole section there:

    Parameters

    s
    Type: System.String

    A string containing a number to convert.

    result
    Type: System.Int32

    When this method returns, contains the 32-bit signed integer value equivalent of the number contained in s, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the s parameter is Nothing or String.Empty, is not of the correct format, or represents a number less than MinValue or greater than MaxValue. This parameter is passed uninitialized.

    Return Value

    Type: System.Boolean
    true if s was converted successfully; otherwise, false.

    *****

    My question remains ... how can it return two things if it's not an instance of a class? It has both a result and a return value; the result is an integer and the return value is a boolean.

    I've set up functions which *sort of* do that, but not directly, and the scope of what's passed into my function has to be high enough that I can "reach it and change it" (visibility).

    That's obviously not how they're doing it.

    What am I missing?


    Please call me Frank :)

    Monday, September 16, 2013 9:53 PM
  • I bet that I do know, now that I think of it.

    The "test" in mine was one of the required parameters (which is "result" in the method).

    If it's cast (i.e., CType or others) then the identity isn't changed - so if they then modify "result" in theirs, "test" in mine in reflects that same change.

    Am I right?


    Please call me Frank :)


    • Edited by Frank L. Smith Monday, September 16, 2013 9:59 PM ...typical Frank typo
    Monday, September 16, 2013 9:58 PM
  • My question remains ... how can it return two things if it's not an instance of a class? It has both a result and a return value; the result is an integer and the return value is a boolean.


    I've set up functions which *sort of* do that, but not directly, and the scope of what's passed into my function has to be high enough that I can "reach it and change it" (visibility).

    That's obviously not how they're doing it.

    What am I missing?

    Thanks for copying the documentation. ;-) I didn't take TryParse literally. I've seen it as an example for any function with such a signature. So I didn't really care about what TryParse in particular returns.

    Frank, I don't really understand your problem. Let's take this example I've posted recently:

       Private Shared Function TryGetClipboardText(ByRef Text As String) As Boolean
    
          Const msg As String = "Clipboard is empty."
    
          Text = Clipboard.GetText
    
          If Text Is Nothing Then
             ShowInformation(msg)
             Return False
          End If
    
          Text = Text.Trim
    
          If Text.Length = 0 Then
             ShowInformation(msg)
             Return False
          End If
    
          Return True
    
       End Function

    Absolutely valid IMO. As I said above: The caller shouldn't complain that 'Text' has changed even if the function returns False because False tells him not to use it.

    EDIT: Someone could tell me just to return the clipboard content, if any, via function return value (As String then) instead, but I'd like to do my checks at the start of a function, the caller of the one above, this way:

          If Not TryGetClipboardText(Text) Then Return False
    


    Armin


    Monday, September 16, 2013 10:03 PM
  • My question remains ... how can it return two things if it's not an instance of a class? It has both a result and a return value; the result is an integer and the return value is a boolean.


    I've set up functions which *sort of* do that, but not directly, and the scope of what's passed into my function has to be high enough that I can "reach it and change it" (visibility).

    That's obviously not how they're doing it.

    What am I missing?

    Thanks for copying the documentation. ;-) I didn't take TryParse literally. I've seen it as an example for any function with such a signature. So I didn't really care about what TryParse in particular returns.

    Frank, I don't really understand your problem. Let's take this example I've posted recently:

       Private Shared Function TryGetClipboardText(ByRef Text As String) As Boolean
    
          Const msg As String = "Clipboard is empty."
    
          Text = Clipboard.GetText
    
          If Text Is Nothing Then
             ShowInformation(msg)
             Return False
          End If
    
          Text = Text.Trim
    
          If Text.Length = 0 Then
             ShowInformation(msg)
             Return False
          End If
    
          Return True
    
       End Function
    Absolutely valid IMO. As I said above: The caller shouldn't complain that 'Text' has changed even if the function returns False because False tells him not to use it.


    Armin

    Right - because it's being passed in by reference, not by value.

    I think I'm starting to understand. :)


    Please call me Frank :)

    Monday, September 16, 2013 10:06 PM

  • Frank, I don't really understand your problem. Let's take this example I've posted recently:

       Private Shared Function TryGetClipboardText(ByRef Text As String) As Boolean
    
          Const msg As String = "Clipboard is empty."
    
          Text = Clipboard.GetText
    
          If Text Is Nothing Then
             ShowInformation(msg)
             Return False
          End If
    
          Text = Text.Trim
    
          If Text.Length = 0 Then
             ShowInformation(msg)
             Return False
          End If
    
          Return True
    
       End Function


    When returning false, is text is nothing or string.empty .. that depend on the content of the clipboard in your code

    Also, if your sub main was decorated with the MTATreadAttribute, the method will thow a  ThreadStateException

    Monday, September 16, 2013 11:55 PM
  • EDIT:

    Regarding exceptions: I agree with you that functions should pass results as return values whenever possible. But this doesn't apply always. If the caller passed Nothing and this is invalid, an ArgumentNullException must be raised. Returning it via function return value wouldn't make sense as the programmer would then check at runtime if he passed a wrong argument at the call. He should better correct the call instead of validating the call afterwards.


    Armin

    This would indeed be true if you're writing some sort of idiot proof library/interface (like the .net framework ;)), in which case the exceptions are part of your model. Most of the time though you'll only do validation the moment data enters your application, and want to handle it right there (say by a messagebox or whatever).

    I'm not a big fan of null checks really, they're overused and therefore often redundant. Your example is imo a language issue that could be more elegantly solved by allowing NOT-nullable reference type parameters/variables (similar to nullable value types).

    I guess it also depends on your debugging method. If you're analyzing logs and stack traces a meaningful log/exception is without doubt much better than some meaningless nullreferenceexception, while if you're using the VS debugger it's likely better to save yourself some code and just let it crash a bit further down the road. Personally I prefer the debugger, a lot.



    • Edited by exstud Tuesday, September 17, 2013 12:05 AM
    Monday, September 16, 2013 11:56 PM

  • Frank, I don't really understand your problem. Let's take this example I've posted recently:

       Private Shared Function TryGetClipboardText(ByRef Text As String) As Boolean
    
          Const msg As String = "Clipboard is empty."
    
          Text = Clipboard.GetText
    
          If Text Is Nothing Then
             ShowInformation(msg)
             Return False
          End If
    
          Text = Text.Trim
    
          If Text.Length = 0 Then
             ShowInformation(msg)
             Return False
          End If
    
          Return True
    
       End Function


    When returning false, is text is nothing or string.empty .. that depend on the content of the clipboard in your code

    Also, if your sub main was decorated with the MTATreadAttribute, the method will thow a  ThreadStateException

    The function returns True if there's a valid String in the clipboard, False otherwise. I don't see the point.

    Not setting MTA would be a programming fault. I don't  handle programming faults in every function, only in the thread's main procedure.


    Armin

    Tuesday, September 17, 2013 2:06 AM
  • EDIT:

    Regarding exceptions: I agree with you that functions should pass results as return values whenever possible. But this doesn't apply always. If the caller passed Nothing and this is invalid, an ArgumentNullException must be raised. Returning it via function return value wouldn't make sense as the programmer would then check at runtime if he passed a wrong argument at the call. He should better correct the call instead of validating the call afterwards.


    Armin

    This would indeed be true if you're writing some sort of idiot proof library/interface (like the .net framework ;)), in which case the exceptions are part of your model. Most of the time though you'll only do validation the moment data enters your application, and want to handle it right there (say by a messagebox or whatever).

    I'm not a big fan of null checks really, they're overused and therefore often redundant. Your example is imo a language issue that could be more elegantly solved by allowing NOT-nullable reference type parameters/variables (similar to nullable value types).

    I guess it also depends on your debugging method. If you're analyzing logs and stack traces a meaningful log/exception is without doubt much better than some meaningless nullreferenceexception, while if you're using the VS debugger it's likely better to save yourself some code and just let it crash a bit further down the road. Personally I prefer the debugger, a lot.



    I agree, I also often wished there was not-nullable. That would safe some time.

    Redundant Null-checks: I agree, but safety first. :-) The callee never knows the caller, so to speak. And I even wouldn't trust myself. How do you call a disease you haven't cured completely and this makes more problems later? I didn't find a good translation online. :) That's like not checking the parameter, hence not noticing the problem where it originates, and later spending more time looking for the problem or fixing the disaster.


    Armin

    Tuesday, September 17, 2013 2:22 AM
  • Exstud,

    I was ready to say that I desagree 100% with you, ... but may be are we just not living in the same world

    If for you 10,000 represent the number of lines in the application, well, ok, then if down the road some functionalities are added or changed in the application and as result of that some method start to behave in an unexpected way, you can take a couple hours before lunch break and fix it.

    But when 10,000 represent the number of methods or classes in the application, it is not the same. Usualy, this misbehaviour means:

     - Bug analysis

     -Work around analysis

    If it is decided that the bug will be fixed,

     - Locate all the dependencies and study of the calls contrext

     - analyse of the consequence of the change on those dependencies

    When fixed,

     - Documentation

     - versioning

     - send the all thing for testing (hoping that it will pass, otherwise, it is all to be start over)

    And likely hundreds of men-hours spend.

    Tuesday, September 17, 2013 2:39 PM
  • In the case you posted, I personally would use that as an opportunity to log the error so the user would not be wondering why he/she only has 999 images after processing 1000.

    Catch ex as exception

    StringBuilder.Append("An error occurred processing the Image " & Image.name, etc ect.....

    End Try

    Tuesday, September 17, 2013 3:52 PM
  • In the case you posted, I personally would use that as an opportunity to log the error so the user would not be wondering why he/she only has 999 images after processing 1000.

    Catch ex as exception

    StringBuilder.Append("An error occurred processing the Image " & Image.name, etc ect.....

    End Try

    I don't disagree with the concept, although I think it would be better to have a class all to itself which would encapsulate the exception message, the exception string itself, and the file's full path.

    Then you can show the user not only which one, but at least give them some idea about the "why".

    Therein lies the rub though, in the words of Hamlet - if they see "GDI+ failure", will they think there's something wrong with their machine?

    But as for logging, in general I completely agree.


    Please call me Frank :)

    Tuesday, September 17, 2013 3:57 PM
  • In the case you posted, I personally would use that as an opportunity to log the error so the user would not be wondering why he/she only has 999 images after processing 1000.

    Catch ex as exception

    StringBuilder.Append("An error occurred processing the Image " & Image.name, etc ect.....

    End Try

    IMO, regarding that example:

    • The author can decide how to write the function:
      a) quit the function after an exception
      b) continue processing skipping the faulty item
      c) add a parameter to the function so that the caller can decide between a) an b)
      Every option is valid, none is wrong or right, but version c) has the highest quality.
    • If b) is possible, a list of failed items should be passed back to the caller

    Oh, and d) is a Callback passed in as a parameter and called in the case of an exception. What about e)? e) If the task is wrapped in a class, raise an event. However, I wouldn't go for e) as there can be multiple event handlers, and every handler could decide differently whether to continue or not.

    I would not provide the information as text. It's up to the caller to bubble it up or format and log or display them. In those cases, whenever more information can be provided, I write a containing class which also can have an overriden ToString method. In this case, the class would proably contain the exception and the image file name or the image index (if an array was the in-parameter).


    Armin


    • Edited by Armin Zingler Tuesday, September 17, 2013 4:16 PM formatting
    Tuesday, September 17, 2013 4:12 PM
  • I was ready to say that I desagree 100% with you, ... but may be are we just not living in the same world

    For just this one time I'll agree with you Crazy, you and me we're complete opposites.

    This is only the 2nd thread we meet, but I already had you listed as a guy with strong technical skills, not afraid and eager to use them. I on the other hand am the guy with similar technical skills but extremely wary to unleash them, mainly because of maintainability and readability reasons. It's really no wonder you're dealing with 10k-method/class applications, and probably enjoying it (I'd probably go WTF/hour crazy and kill myself).

    I'm sure we'll clash again in the near future, hope you're looking forward to it as well. Peace.


    • Edited by exstud Tuesday, September 17, 2013 4:40 PM
    Tuesday, September 17, 2013 4:32 PM
  • I was ready to say that I desagree 100% with you, ... but may be are we just not living in the same world

    For just this one time I'll agree with you Crazy, you and me we're complete opposites.

    This is only the 2nd thread we meet, but I already had you listed as a guy with strong technical skills, not afraid and eager to use them. I on the other hand am the guy with similar technical skills but extremely wary to unleash them, mainly because of maintainability and readability reasons. It's really no wonder you're dealing with 10k-method/class applications, and probably enjoying it (I'd probably go WTF/hour crazy and kill myself).

    I'm sure we'll clash again in the near future, hope you're looking forward to it as well. Peace.


    exstud

    Still here an advice,..

    No matter the size of the application,  

    Be rigorous.

    Establish the way you think you should handle the thing and stick with it

    Dont mixup  UI code,  algorithm logic code  and helper method code

    When you write a method, a class,  make it right and solid ... May be will you spend a few more hours now to implement fool proof, but you will then be able to re-use it for the rest of your life ( At the end of the line, those few hours invested will pay)


    • Edited by Crazypennie Tuesday, September 17, 2013 9:29 PM 1324456
    Tuesday, September 17, 2013 5:09 PM
  • Not the reply I expected, a good reminder as well, Tx! Respect.
    • Edited by exstud Tuesday, September 17, 2013 7:45 PM
    Tuesday, September 17, 2013 7:32 PM