Finally

From Xojo Documentation

Language Keyword

Contains code that will run after a method or function is finished, even if a RuntimeException has occurred.

Usage

Try

// Your code

Catch
[Finally]

//code that executes even if runtime exceptions were raised

End [ Try ]

Notes

Sometimes a method needs to do some cleanup work whether it is finishing normally or aborting early because of an exception. The optional Finally block at the end of a method or function runs after its exception handlers, if it has any. Code in this block will be executed even if an exception has occured, whether the exception was handled or not.

More commonly you will use Finally as part of a Try...Catch statement.

For example, you can write:

Sub SomeFunction()
// some code here...
Finally
// some more code that will always execute (unless a Return statement is used, see below)
End Sub

However, the code in the Finally block does not execute if you exit the method with a Return statement. See the following code:

Sub SomeFunction(x As Integer)
If x = 0 Then
Return // -> the Finally block won't execute
End If
Finally
Break // Debugger would stop here to check if it executes
End Sub

See also the entries for the Sub and Function statements.

Returning From a Finally Block

You should not use Return statements within a Finally block. The execution of a Return statement will cause any exceptions raised inside the Try and Catch blocks to be lost to the caller.

Here is an example:

Sub Test()
Raise New OutOfBoundsException
Finally
Return // This is a bad idea!
End Sub

If you call this Test method, it will return as if there had been no exception raised inside. Therefore, avoid Return statements at all costs. If you really want to drop any raised exceptions, it is suggested that you be more explicit of that intention by adding a Catch block.

Also note that because a Return statement will skip any following Finally blocks, code that requires cleanup should be nested in its own Try block, with any return statement outside that block. Finally blocks at the method level are better avoided.

Sample Code

This simple example shows a Finally block that executes even after an exception.

Try
Raise New RuntimeException
Finally
// Executes even though the exception is not handled
MsgBox("Finally")
End Try

This example shows how to wrap code requiring cleanup inside a Try block, before returning a value.

Function GetRandomSeed() As Int64
#If TargetMacOS
Const libc = "libc.dylib"
#Endif
#If TargetLinux
Const libc = "libc.so"
#Endif

Const O_RDONLY = &o0000

Soft Declare Function open lib libc (path As CString, oflag As Integer) As Integer
Soft Declare Function read lib libc (fildes As Integer, ByRef buf As Int64, nbyte As Integer) As Integer
Soft Declare Function close lib libc (filedes As Integer) As Integer

Dim theSeed As Int64
Dim fd As Integer = open("/dev/random", O_RDONLY)
If fd = -1 Then
// an error occurred.
Return 0
End If

Try
Const sizeOfInt64 = 8
Dim read_bytecount As Integer = read(fd, theSeed, sizeOfInt64)

Finally
Dim close_result As Integer = close(fd)
fd = -1
End Try

Return theSeed
End Function

See Also

Catch, Function, Sub statements; Exception, Try statements.