How to correctly write Try..Finally..Except statements?

Viewed 67925

Take the following code as a sample:

procedure TForm1.Button1Click(Sender: TObject);
var
  Obj: TSomeObject;
begin
  Screen.Cursor:= crHourGlass;

  Obj:= TSomeObject.Create;
  try
    // do something
  finally
    Obj.Free;
  end;

  Screen.Cursor:= crDefault;
end;

if there was an error happening in the // do something section, the TSomeObject that was created I assume will not be freed and the Screen.Cursor will still be stuck as an Hour Glass, because the code was broke before getting to those lines?

Now unless I am mistaking, an Exception statement should be in place to deal with any such occurence of an error, something like:

procedure TForm1.Button1Click(Sender: TObject);
var
  Obj: TSomeObject;
begin
  try
    Screen.Cursor:= crHourGlass;

    Obj:= TSomeObject.Create;
    try
      // do something
    finally
      Obj.Free;
    end;

    Screen.Cursor:= crDefault;
  except on E: Exception do
  begin
    Obj.Free;
    Screen.Cursor:= crDefault;
    ShowMessage('There was an error: ' + E.Message);
  end;
end;

Now unless I am doing something really stupid, there should be no reason to have the same code twice in the Finally block and after, and in the Exception block.

Basically I sometimes have some procedures that may be similar to the first sample I posted, and if I get an error the cursor is stuck as an Hour Glass. Adding the Exception handlers help, but it seems a dirty way of doing it - its basically ignoring the Finally block, not to mention ugly code with copy-paste from the Finally to Exception parts.

I am still very much learning Delphi so apologies if this appears to be a straight forward question/answer.

How should the code be correctly written to deal with the Statements and correctly freeing objects and capturing errors etc?

7 Answers

If you found your way here and were looking for how you make a try-except-finally construct from C# in Delphi:

// C#
try
{
    // Do something
}
catch
{
    // Exception!
}
finally
{
    // Always do this...
}

The answer is that you cannot do this directly. Instead, as @sacconago hints at, nest the try blocks as follows:

// Delphi
try
    try
        // Do something
    except
        // Exception!
    end;
finally
    // Always do this...
end;

One nice feature of Delphi is that you can nest the blocks as try...except...finally or try...finally...except, though the former would be more common.

Related