Try ... Catch ... Finally

Why EndOfLine.UNIX on one condition and just EndOfLine on the other?

Bad edit :slight_smile: That was copied from the Windows target code and the data is being written to a Linux server task where EOL type matters, but my mind was in Unix-land when I edited the original, so left that off.

Out of curiosity, why do you have the line

TOS.Flush

since the Close statement will force a Flush anyway? Typically, Flush is used to write out the contents of the file buffer while keeping the file open.

2 Likes

It’s an old habit and related to the old versions of Xojo (this code is being brought forward from an original REAL.Studio project from 2007r3.

I’m not sure to see the difference between the code above and the code below :

If f <> Nil And Not f.Exists Then
  Try
    theTOS = TextOutputStream.Create(f)
    If defaultEntry <> "" Then
      theTOS.Write defaultEntry + EndOfLine.UNIX
    Else
      theTOS.Write "" + EndOfLine
    End If
    theTOS.Flush
  Catch e As IOException
    // Permissions issue?
  End Try
  If theTOS <> Nil Then
    theTOS.Close
  End If
End If

In both case theTOS.Close will be done if not Nil ?! (yes I read the documentation about Finally).

In this particular case, they are equivalent.

1 Like

The nuance with Finally is that it will be executed regardless of whether you caught the exception or not. Consider this case

var t as TextOutputStream
try
   t.write("x")
catch e as IOException
   MsgBox("caught an exception")
end try
MsgBox("did we get here?")

In this case, we will get a NilObjectException, which will not be caught. The MsgBox after the try/catch will never be excecuted, because the uncaught exception will immediately exit the method and propagate up the call stack. As opposed to

var t as TextOutputStream
try
   t.write("x")
catch e as IOException
   MsgBox("caught an exception")
finally
   MsgBox("finalizing")
end try
MsgBox("did we get here?")

Now we will get the “finalizing” MsgBox, but not “did we get here?” You use Finally to clean up in the case where some completely unexpected and/or unrecoverable exception occurs.

2 Likes

That will still crash if you get an IOException because then theTOS is nil, hence “theTOS.Close” will cause a NOE. There are two solutions to this:

  1. Check for theTOS <> nil
  2. add a “return” inside every “catch” clause because the finally code won’t be called if the function issues a “return” statement.

In this example you do not need “Finally” unless the code in the try can raise exceptions other than the ones you catch - which is probably not the case here.

Finally is needed when you call code that you are not sure about which exceptions it may raise, and if you do not want to add a catch-all with catch e as RuntimeException. In this case, if the deeper code raises an exc that you do not catch, you may still want to clean up, such as delete a just-created file, before code higher up in the calling chain will catch the exception and handle it gracefully - but since that higher code does not know you created a file, you need to do that in your local finally handler.

However, remember that, in order for the finally code to be called, you must not leave the function through a return statement!

1 Like

Thank you Tim and Thomas, that’s more clear for me. I was interested in the Finally instruction because I may code better the way I read my Preferences files.
In all my programs, I read prefs file at startup to get folderitem, make Arrays, Dates and so on. Of course I try to avoid problem even if the guy edit the PrefFile in TextEdit, but problem may still occur. The file may be corrupted etc.
Then I read the file in a string and I do the job in a Method like :

If MyPrefFil.Exists Then
  Read PrefTextFile and set variables
  MyFolderItem = Read…
  MyArray = Read…
  MyDate = Read…
Else
  MyFolderItem = Default…
  MyArray = Default…
  MyDate = Default…
End If

Exception TypErr
  System.Beep
  MyFolderItem = Default…
  MyArray = Default…
  MyDate = Default…

I have two times the same code. I thought about put a Goto: Exception in the Else but I’m not sure it’s a good thing.
When I read this topic and learn Finally instruction exists, I said to myself that maybe there is a good way to do with this.

1 Like

I’ve been using two Modules for at least 10 years to save preference files for both mac and win that does everything you are trying to do. XMLPreferences written by Joseph Sharp, (E-mail: joesharp@mac.com), and another called XMLdictionary 1.2.6 by Kevin Ballard, (kevin@sb.org http://www.tildesoft.com) that does everything you are trying to accomplish with your preferences code. I think the only thing I have ever had to modify was eliminating code for Mac Type that was no longer valid.

Syntax is similar for most variable types. Here is what is used for a string:
somevariable As String = GetPrefString(("SomeKeyName", "Default Value")

Saving is like this
SetPrefString(("SomeKeyName", somevariable)

I’m not sure how hard irt would be to find this any more, but if you PM Me I’ll send it to you to look at.

Could it be that you posted this reply to the wrong thred, @Tom_Dixon ?

Nope. It was a response to Thomas Robisson about him reading his preference files. There might be a better way to do what he is doing that he might want to take a look at despite the fact that the thread is about Try, Catch Finally and Thomas isn’t the OP.

A better way to avoid thread confusion is quoting part of what you intend to talk aside instead of being on topic.

Like:

I’ve been using two Modules for…

Thank you, I heard about module for pref but I don’t want to rewrite all.
My question was, asked differently is : As there is a way to use Finally in a Try Catch , is there a way to use Finally with Exception ? It seems not.

What you’re doing here:

Could be translated to a modern Try/Catch like:

Try
  If MyPrefFil.Exists Then
    Read PrefTextFile and set variables
    MyFolderItem = Read…
    MyArray = Read…
    MyDate = Read…
  Else
    MyFolderItem = Default…
    MyArray = Default…
    MyDate = Default…
  End If
Catch err
  System.Beep
  MyFolderItem = Default…
  MyArray = Default…
  MyDate = Default…
Finally
  // whatever
End

1 Like