Execute News

Des nouvelles fraîches de http://www.execute.frRSS [Home]

Utilisation des Records Managés sous Delphi Sydney

Publié le 11/08/2020 [Delphi]
Une des grosses nouveauté de Sydney au niveau du compilateur est le support des Records Managés.

Cette fonctionnalité est assez intéressante dans son fonctionnement, elle permet d'appeler une fonction automatiquement pour initialiser un Record et une autre pour faire le ménage.

Prenons un exemple simple.
procedure TForm1.Button1Click(Sender: TObject);
var
  SL: TStringList;
begin
  SL := TStringList.Create;
  try
    SL.Add('Hello');
    SL.Add('World');
    ShowMessage(SL.Text);
  finally
    SL.Free;
  end;
end;

dans cet exemple classique (et bidon) j'instancie un StringList qui est détruit à la fin de la procédure...mais voici comment éviter le try/finally/end
type
  TStringListRecord = record
    SL: TStringList;
    class operator Initialize(out R: TStringListRecord);
    class operator Finalize(var R: TStringListRecord);
  end;

class operator TStringListRecord.Initialize(out R: TStringListRecord);
begin
  R.SL := TStringList.Create;
end;

class operator TStringListRecord.Finalize(var R: TStringListRecord);
begin
  R.SL.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  R: TStringListRecord;
begin
  R.SL.Add('Hello');
  R.SL.Add('World');
  ShowMessage(R.SL.Text);
end;

et voilà ! grâce aux deux opérateurs déclarés, TStringListRecord instancie automatiquement un TStringList qui est libéré en fin de procédure car la variable R est locale.

Alors évidemment ça n'a d'intérêt que si vous utiliser (TStringListRecord) à différents endroits, mais ce n'est qu'un exemple...et on peut aussi imager utiliser un <generic> pour faire des choses plus évoluées.
type
  TRecord<T:class,constructor> = record
    Instance: T;
    class operator Initialize(out R: TRecord);
    class operator Finalize(var R: TRecord);
  end;

class operator TRecord<T>.Initialize(out R: TRecord);
begin
  R.Instance := T.Create;
end;

class operator TRecord<T>.Finalize(var R: TRecord);
begin
  R.Instance.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  R: TRecord<TStringList>;
begin
  R.Instance.Add('Hello');
  R.Instance.Add('World');
  ShowMessage(R.Instance.Text);
end;