Enregistrements managés personnalisés

De RAD Studio
Aller à : navigation, rechercher

Le type enregistrement de Delphi prend maintenant en charge la finalisation et l'initialisation personnalisées au-delà des opérations par défaut réalisées par le compilateur pour les enregistrements managés (c'est-à-dire les enregistrements ayant des champs dont les types sont gérés par des chaînes de type compilateur). Vous pouvez déclarer un enregistrement avec du code d'initialisation et de finalisation personnalisé indépendamment du type de données de ses champs, et écrire ce code d'initialisation et de finalisation personnalisé. Vous devez pour cela ajouter un constructeur sans paramètres au type d'enregistrement et un destructeur (vous pouvez avoir l'un sans l'autre).

Voici ci-dessous un extrait de code simple :

type
  TMyRecord = record
    Value: Integer;
    constructor Create;
    destructor Destroy;
  end;

Vous devez écrire le code pour les deux méthodes. La principale différence entre ce nouveau constructeur et ce qui existait auparavant pour les enregistrements se situe au niveau de l'invocation automatique. Lorsque vous écrivez du code similaire au code ci-dessous, vous pouvez invoquer le constructeur par défaut et le destructeur, puis terminer par un bloc try-finally généré par le compilateur pour votre instance d'enregistrement managé.

procedure TForm5.btnMyRecordClick(Sender: TObject);
var
  my1: TMyRecord;
begin
  Log (my1.Value.ToString);
end;

Par ailleurs, l'extrait de code ci-dessous vous permet d'invoquer explicitement le constructeur par défaut de l'enregistrement.

myrec := TMyRecord.Create;
Attention: Selon la façon dont vous écrivez le code, le constructeur par défaut peut être invoqué deux fois, implicitement par le compilateur et dans votre code. Dans le cas de déclarations de variables inline, cela ne se produit pas.

L'opérateur Assign

Les enregistrements managés personnalisés vous permettent d'exécuter du code personnalisé de façon à assigner un enregistrement à un autre enregistrement. Plutôt que de copier l'ensemble des données, champ par champ, vous pouvez effectuer différentes tâches, garder une copie de certains champs, dupliquer un objet auquel un enregistrement fait référence, ou toute autre opération personnalisée. Le nouvel opérateur est invoqué par la syntaxe := mais est défini en tant que Assign :

type
  TMyRecord = record
    Value: Integer;
    class operator Assign (var Dest: TMyRecord; const [ref] Src: TMyRecord);

La définition de l'opérateur doit suivre des règles précises, y compris le fait d'utiliser le premier paramètre comme un paramètre de référence et le second comme un paramètre var ou const transmis par référence. Si vous ne procédez pas ainsi, le compilateur enverra des messages d'erreur comme ci-dessous :

[dcc32 Error] E2617 First parameter of Assign operator must be a var parameter of the container type
[dcc32 Hint] H2618 Second parameter of Assign operator must be a const[Ref] or var parameter of the container type

L'extrait de code ci-dessous invoque l'opérateur Assign :

var
  my1, my2: TMyRecord;
begin
  my1.Value := 22;
  my2 := my1;

L'opérateur Assign est utilisé conjointement avec des opérations d'assignation comme dans l'exemple ci-dessus, mais aussi si vous utilisez une assignation pour initialiser une variable inline (dans ce cas, le constructeur par défaut n'est pas appelé) :

 var my4 := my1;

Constructeur de copie

Lorsque vous transmettez un paramètre d'enregistrement ou que vous souhaitez créer un nouvel enregistrement à partir d'un enregistrement existant, vous pouvez définir un constructeur de copie : un constructeur qui prend un enregistrement du même type que le paramètre. Il peut arriver que vous souhaitiez aussi avoir un constructeur par défaut, vous devez dans ce cas les marquer avec la directive overload :

  TMyRecord = record
    constructor Create; overload;
    constructor Create (const mr: TMyRecord); overload;

Si vous définissez une méthode ou une procédure avec un paramètre valeur normal (non transmis par const ou var), il utilisera le constructeur de copie et non un appel d'assignation lorsque vous l'invoquerez :

procedure ProcessRec (mr: TMyRecord);
begin
  Log (mr.Value.ToString);
end;

Sachez que le destructeur Destroy sera aussi appelé à la fin de la procédure. Le constructeur de copie peut aussi être invoqué en utilisant la déclaration de variable inline suivante :

 var my3 := TMyRecord.Create (my1);