Try Catch expense and best practice

Hello,

Normally I use Try/Catch for just one exception type and a narrow section of code. Looking at the future of Sockets they will use Try/Catch instead of checking True/False conditions. Is it better to have many Try/Catch loops in a method, or have most of the socket code in a larger scope with several catch types at the end? I assume one major reason for this change is code execution speed, not having to check for all the True/False conditions - assume all is well unless an exception is triggered.

That being said, here is some example code:

Dim mbTest As NEW MemoryBlock(10) Try mbTest.StringValue(9,5) = "Hello" Catch erData As NilObjectException MsgBox("Will not execute this, cause no Nil Object issues") Catch erData As RunTimeException MsgBox("Will execute this") Catch erData As OutOfBoundsException MsgBox("Yes, out of bounds; but won't execute this") End Try
In the code above, Catch RunTimeException and Catch OutOfBoundsException need to switch places if you want to actually catch the Out of Bounds triggered by trying to write “ello” beyond the size of mbTest.

Is RunTimeException the only catch ALL where something like this matters, or are their other catch types where the order is important?

Thanks.

the only reason you need to swap the order is because RuntimeException is the parent class of all other exceptions so its like saying “catch everything” - so no more specific subtypes are caught after that

as for “best practice” it really depends on the code, how it functions and what you expect to happen IF you catch an error or if you dont

in a simple linear bit of code where you’d normally bail out an do nothing IF there was some error then just one try catch might suffice

if its a loop where you are trying to do something repeatedly in the loop and want the loop to proceed even in the case you catch an error then you might have a try catch inside the loop

Not sure there’s a single “best” answer for all situations

Whether you put the try catch inside a loop or outside a loop depends on the behavior you’re looking for. If your loop can continue processing after handing an error, put the catch inside the loop.

RuntimeException is the superclass for all the others. As Norman mentioned, you’re basically saying “Hey, I want everything here.” Don’t do that. If you’re not catching a specific exception, you can’t really handle it. Anything unhandled should bubble to UnhandledException – where what is considered best practice seems to still be up for debate. My opinion is that terminating the app is best because it’s an exception you haven’t handled, you don’t know what it is, or what effects it has. Safer to quit and start again.

Catching exceptions is a different mindset than the older check for error codes. If you (or anyone!) have any other questions, I think this would be a great place to discuss best practices :slight_smile:

as Tim said, do not catch RuntimeException
catch the things you CAN handle and do want to handle and let others go by

“catch everything” is generally NOT really what you actually want to do

and especially not “catch everything and ignore it”

Please don’t catch RunTimeException.
Catch the ones you explicit handle here.

and if you happen to catch all exceptions, don’t forget to re-raise the EndExceptions and ThreadEndExceptions. See: http://documentation.xojo.com/api/exceptions/exception.html / http://documentation.xojo.com/api/code_execution/try.html

Except for the unfortunate places in the old-new framework that raise a RuntimeException instead of a subclass, like:

Xojo.IO.FolderItem.CreateAsFolder Xojo.IO.SpecialFolder.ApplicationSupport Xojo.Core.TextEncoding.ConvertTextToData etc.

I really hope API 2.0 doesn’t do that…

Dunno but I suppose if its not that way them it can be raised when we see a beta

Xojo.IO.FolderItem.CreateAsFolder - huh that probably should have been an IOException
Xojo.IO.SpecialFolder.ApplicationSupport - same
Xojo.Core.TextEncoding.ConvertTextToData - maybe a UnsupportedOperationException

I’d file those as bug reports if they havent been already

Reopening this thread to ask about best practices for CATCH properties. This is what I’m assuming is a really dumb question, but that’s just the way I roll.

If I have code like this (which is guaranteed to fail):

try
  dim aa as dictionary
  aa.Value("foo") = "bar"
  MsgBox "All is as it was"
  
Catch e As NilObjectException
  MsgBox "Whoops: " + e.Message + "  reason:" + e.Reason + "  #" +str(e.ErrorNumber)
end try

And I run it, the values for e.Message and e.Reason are blank, and e.ErrorNumber is zero.

Is this normal? When should I expect to see useful information in these properties?

I’m guessing I missed the semester where this was discussed; or, I’m just losing all my neurons.

Thanks!

When the operating system provides it. Things like IOException will have more useful information. Or where you write your own exceptions and provide that information.

Thanks Tim. So the catch properties only come from the OS?

For example in NilObjectException, it would be fabulous if Xojo could put into the message something about the object which is Nil. Sometimes in a complex statement it takes a while to work out which one is the problem.

How would they give you information about an object that doesn’t exist?

Answering that is above my pay grade. I do know that in some other debuggers I’ve used over the decades, some of them provided more useful information about what the actual problem was, rather than just pointing to a line number.

If you are using try catch to test for a specific exception then you already know the exception type. So why not write

MsgBox “Whoops: " + e.Message + " reason: NilObjectException in " + CurrentMethodName + " #” +Str(e.ErrorNumber)

I put your code into a PushButton, and get

Personally I use a catch all, so I put your code into a PushButton, added my error code, and ran it:

[code]Dim aa As dictionary
aa.Value(“foo”) = “bar”
MsgBox “All is as it was”

Exception err

If Not Module_ErrorHandling.HandleException(err, CurrentMethodName) Then
Raise err // this lets me know exactly where the exception
End If // happened and my message dialog reports this along
// with what type of exception it was[/code]

The module opens a window that shows:

[quote]Sorry, but an error occured. It should not happen but unfortunately it has. Please report what you were doing before the program fell over.

NilObjectException in Window1.PushButton1.Action[/quote]

and gives the user the options to (1) send an email with the stack and then (2) save the data as a new file (in the hope something can be recovered if needed)

Actually it is kinda possible.

I added a property to my ErrorModule

Public Property ErrorLocation as String = "Error location"

Wherever I would have a try catch I would set (and reset) that property instead, so the code becomes

[code]ErrorLocation = “Dictionary aa”
Dim aa As dictionary
aa.Value(“foo”) = “bar”
ErrorLocation = “”

Exception err

If Not Module_ErrorHandling.HandleException(err, CurrentMethodName) Then
Raise err // this lets me know exactly where the exception
End If // happened and my message dialog reports this along
// with what type of exception it was[/code]

and my email now says:

[quote]NilObjectException in Window1.PushButton1.Action

Error probably caused by: Dictionary aa[/quote]

Btw you can simply sprinkle locations throughout your code:

ErrorLocation = "Location 1" [some code] ErrorLocation = "Location 2" [some more code] ErrorLocation = "Location 3" [some more code]

Getting

tells you it is between Location 2 and 3

Improving the provided RuntimeException information is a long standing request. Some of them are listed here: