Difference between revisions of "Finally"

From Lazarus wiki
Jump to navigationJump to search
 
(4 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 
{{Finally}}
 
{{Finally}}
  
The [[Reserved word]] <syntaxhighlight lang="pascal" enclose="none">finally</syntaxhighlight> identifies the [[Block|block]] that should always be processed, regardless of whether an error has occurred or not.
 
  
Example:
+
Back to [[Reserved words]].
<syntaxhighlight>
+
 
 +
 
 +
The reserved word <syntaxhighlight lang="pascal" inline>finally</syntaxhighlight> identifies a [[Block|block]] of code that should always be processed, regardless of whether the preceding <syntaxhighlight lang="pascal" inline>try</syntaxhighlight> block was fully executed or has been exited early (in case of an [[Exception]], [[Exit]], [[Break]] or [[Continue]]).
 +
 
 +
== Examples ==
 +
 
 +
Simple example:
 +
 
 +
<syntaxhighlight lang=pascal>
 
begin
 
begin
 
   ...
 
   ...
 
   try
 
   try
     ... // Action
+
     ...   // code to check
 
   finally
 
   finally
     ... // Final work, which should be done even in case of error
+
     ...   // code which should always be executed even if try exits early
 
   end;
 
   end;
 
   ...
 
   ...
Line 16: Line 23:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
Example with error handling:
  
Example (in this example, the <syntaxhighlight lang="pascal" enclose="none">finally</syntaxhighlight> block is always executed):
+
<syntaxhighlight lang=pascal>
 
 
<syntaxhighlight>
 
 
begin
 
begin
 
   ...
 
   ...
 
   try
 
   try
 
     try
 
     try
       ... // instructions to check
+
       ... // code to check
     except // error handling
+
     except  
       ...
+
       ... // error handling
 
     end;
 
     end;
   finally // always instructions to be processed
+
   finally
     ...
+
     ...   // code which should always be executed even if try exits early
 
   end;
 
   end;
 
   ...
 
   ...
 
end;
 
end;
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
== 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:
 +
<syntaxhighlight lang=pascal>
 +
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;
 +
</syntaxhighlight>
 +
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:
 +
<syntaxhighlight lang=pascal>
 +
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;
 +
</syntaxhighlight>
 +
 +
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 <syntaxhighlight lang="delphi" inline>finally</syntaxhighlight> part is ''not'' executed if a {{Doc|package=RTL|unit=system|identifier=halt|text=<syntaxhighlight lang="delphi" inline>halt</syntaxhighlight>}} occurred.
  
 
== See also ==
 
== See also ==

Latest revision as of 15:00, 14 August 2023

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