I know it sounds like an old stupid question but I searched all over the internet and I still don't understand one thing. I understand that try-finally will run the finally code before stopping for error (or don't stopping when no exceptioned was raised) and that try-except will run the except code when exception is raised. But what I still don't understand is the point of try-except within try-finally statements. I'll write an example

What I always do is something like this:

a:=x.Create; try a.DoRiskyStuff; except ShowMessage('Error!'); end; a.free; 

I have never in a years used a finally clause because I always handle the errors and I never understood what is the point to use them both nested together. What's bad about my solution? Why in examples it's common to use something like this:

a:=x.Create; try try a.DoRiskyStuff; except ShowMessage('Error!'); end; finally a.free; end; 

What's the difference? Why should somebody use a finally clause when all cleanup can be done after the try-except?

Thank you very much for any asnwers!

Edit: I changed the create lines so some of you want bash me for it ;)

15

1 Answer

There are two big differences between those two constructs. A technical one and a semantical one.

Technical

Technically, the difference is that the finally block will always be executed, even if there is no exception, while the except block is only executed when there is an exception.

The finally block is even executed when you exit the function early using Exit in a try-finally block.

Additionally, the finally block does not swallow the exception, while the except block generally swallows it, and it can only escape the block if the type of exception does not match the exception types you specify in on ... do, or if you manually re-raise it.

Semantical

The except block is meant to handle the exception(s), while the finally block is not. The finally block is meant to contain code that should be executed regardless of an exception, i.e. mainly to protect resources. That is why you should do:

X := TY.Create; try // Code that may raise an exception. finally X.Free; // Free resource, even if there was an exception. // Exception is NOT handled. end; 

and:

try // Code that may raise an exception. except // Handle the kind of exceptions you can handle. end; 

Note that resource protection with finally is not limited to memory and Free. You can restore/undo/close anything that should be restored/undone/closed, i.e. close opened files, close open connections, shut down hardware that was started, restore mouse pointers to their previous form, etc.etc.

So you can also use it for code like:

Cursor := crMultiDrag; try // Code that may raise exception. finally Cursor := crDefault; end; 
7