Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi try finally on multiple objects

Tags:

delphi

I have written this piece of code:

 FD := TList<double>.Create;
 FN := TList<double>.Create;
 RemList := TList<double>.Create;
 dati := TStringList.Create;

 try

  try

   //code

  except
   on E : Exception do 
   ShowMessage('Incorrect values. Error: ' + E.Message);
  end;

 finally

  if Assigned(dati) then
   dati.Free;

  if Assigned(FD) then
   FD.Free;

  if Assigned(FN) then
   FN.Free;

  if Assigned(RemList) then
   RemList.Free;

 end;

I am using firemonkey so I won't have problems when I'll run this on mobile devices because ARC will manage the lifetime. But is this code safe when I am on windows?

I have read that I cannot have a finally and a catch all together so I need to have a nested try block. I guess that the best way is this:

FD := TList<double>.Create;
try

 FN := TList<double>.Create;
 try

  RemList := TList<double>.Create;
  try

   //and so on...

  finally
   Rem.Free;
  end;

 finally
  FN.Free;
 end;

finally
 FD.Free;
end;

Here I am sure that I'll free the object in any case and in a safe way but the code is hard to read. I have seen that Marco Cantu is suggesting the 2nd approach in object pascal handbook and I understand it, but in my case I want to avoid it.

Can something wrong happen in the first block of code I have written?

like image 331
Raffaele Rossi Avatar asked Mar 25 '26 17:03

Raffaele Rossi


1 Answers

If I was you I'd use the second block of code because as you already know it's better; the TList<double>.Create (like the other constructors) are "safe" as you say but it's better if you always assume that there is a risk behind the corner.

Note that when I say safe I mean that they won't raise an exception if you call them in that way. An exception could happen in any case that you maybe cannot predict, so you really should protect the code with a try finally.

You are also using the Assigned() which is useless. If you look at the implemetation of Free you will find this code (it's also commented):

procedure TObject.Free;
begin
// under ARC, this method isn't actually called since the compiler translates
// the call to be a mere nil assignment to the instance variable, which then calls _InstClear
{$IFNDEF AUTOREFCOUNT}
  if Self <> nil then
    Destroy;
{$ENDIF}
end;

The Assigned() returns true or false if the object is equal to nil or not, so basically you're doing an useless double check.

like image 183
Alberto Miola Avatar answered Mar 31 '26 04:03

Alberto Miola



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!