Finally

From Lazarus wiki
Jump to navigationJump to search

Deutsch (de) English (en) suomi (fi)


Back to Reserved words.


The reserved word finally identifies a block of code that should always be processed, regardless of whether the preceding try block was fully executed or has been exited early (in case of an Exception, Exit, Break or Continue).

Examples

Simple example:

begin
  ...
  try
    ...    // code to check
  finally
    ...    // code which should always be executed even if try exits early
  end;
  ...
end;

Example with error handling:

begin
  ...
  try
    try
      ...  // code to check
    except 
      ...  // error handling
    end;
  finally  
    ...    // code which should always be executed even if try exits early
  end;
  ...
end;

Non-Exception Code

Despite the name, Try-Finally is not strictly tied to the usage of exceptions, and also provides benefits in code where no exceptions can be raised. The reason for this is that the Finally block will always be executed, even if the try block exits early.

This can be very useful e.g. for the Break Fast Break Even paradigm, where Exit or other jumps (such as Break or Continue) are used:

function CheckFormat(const CSVString: String): Boolean;
var
  sl: TStringList;
begin
  Result := False;
  sl := TStringList.Create;
  try
    sl.Delimiter := ';';
    sl.StrictDelimiter := True;
    sl.DelimitedText := CSVString;

    if sl.Count <> RowCount then
      Exit; // Will automatically execute the finally block before exiting
    // Check field data, e.g.
    if not isNumber(sl[1]) then
      Exit; // Will automatically execute the finally block before exiting
    // ...
  finally
    sl.Free;
  end;
  // All checks passed
  Result := True;
end;

Because of the try-finally, the code can simply call exit, and the finally block ensures that sl will be freed afterwards. Without the try-finally, each of these blocks would require a seperate sl.Free call:

function CheckFormat(const CSVString: String): Boolean;
var
  sl: TStringList;
begin
  Result := False;
  sl := TStringList.Create;
  sl.Delimiter := ';';
  sl.StrictDelimiter := True;
  sl.DelimitedText := CSVString;

  if sl.Count <> RowCount then
  begin
    sl.Free;
    Exit;
  end;

  if not isNumber(sl[1]) then
  begin
    sl.Free;
    Exit;
  end;

  // ...

  sl.Free;
end;

Therefore try-finally can even in code without exceptions, help to ensure that the cleanup is performed, without having to consider each exit point individually

Caveats

The finally part is not executed if a halt occurred.

See also