I have seen a number of discussions recently showing that some developers can be confused over try/except and try/finally blocks. I can give an example in the kind of work that I was doing this morning.
I often read or write to an external device (let's just call it "the device" as it could be any external device). That device can sometimes send back confusing errors that I try to trap. However because those errors are confusing, I must let the user know all the various issues and ways around them.
Here's a simplified version of my code (the procedures can raise their own exception with the error message returned from the device).
curSave : TCursor;
curSave := Screen.Cursor;
Screen.Cursor := crHourGlass; // Show hourglass cursor
OpenDeviceConnection; // each will raise an exception if error
If not CloseConnection then // raise my own error
raise exception.create('Cant Close Connection');
// return the cursor to what it was
Screen.Cursor := curSave;
// the original exception is now being handled
// we can re-raise it, but in this case we'll
// raise a new exception with additions
on e:exception do
raise exception.create(e.message + #13+#10
+ 'Please check that the device is switched on' +#13+#10
+ 'and that the cables are properly connected.');
Exceptions created by any of the procedure calls will now result in an error message something like the following...
Note that I have also placed a try/finally block inside the try/except. This is to ensure that we get the cursor back.
I can raise an exception myself with "raise exception.create", the process then heads immediately to the except block, but before doing that, it must complete the finally block.
The order that finally and except will be executed depends on the order that you give it. In the above sequence, finally will be completed before the except. Usually you will see them the other way around where the exception is processed before the finally block.