Benutzerdefinierte verwaltete Records

Aus RAD Studio
Wechseln zu: Navigation, Suche

Der Delphi-Record-Typ unterstützt jetzt zusätzlich zu den Standardoperationen, die der Compiler für verwaltete Records durchführt (d. h. Records mit Feldern mit Typen, die vom Compiler verwaltet werden, z. B. Strings) benutzerdefinierte Initialisierung und Finalisierung. Sie können einen Record mit benutzerdefiniertem Initialisierungs- und Finalisierungscode undabhängig von Datentyp der Felder deklarieren und Sie können diesen Initialisierungs- und Finalisierungscode schreiben. Dies wird erreicht, indem dem Record-Typ ein parameterloser Konstruktor und ein Destruktor hinzugefügt wird (nur einer von beiden ist auch möglich).

Unten finden Sie ein einfaches Codefragment:

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

Sie müssen den Code für die beiden Methoden schreiben. Der große Unterschied zwischen diesem neuen Konstruktor und den früheren Möglichkeiten bei Records ist der automatische Aufruf. Wenn Sie ähnlichen Code wie den unten dargestellten schreiben, können Sie den Standardkonstruktor und den Standarddestruktor aufrufen und erhalten einen try-finally-Block, den der Compiler für die verwaltete Record-Instanz generiert.

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

Mit dem Codefragment unten können Sie den Standardkonstruktor des Records auch explizit aufrufen.

myrec := TMyRecord.Create;
Achtung: Je nachdem, wie Sie den Code schreiben, könnte der Standardkonstruktor auch zweimal aufgerufen werden und zwar implizit vom Compiler und von Ihrem Code. Bei Inline-Variablendeklarationen kann das nicht vorkommen, in anderen Fällen wäre es aber möglich.

Der Operator "Assign"

Mit benutzerdefinierten verwalteten Records können Sie auch benutzerdefinierten Code ausführen, um einem Record einem anderen zuzuordnen. Anstatt die gesamten Daten feldweise zu kopieren, können Sie verschiedene Aufgaben ausführen, eine einzelne Kopie bestimmter Felder beibehalten, ein Objekt, auf das ein Record verweist, duplizieren oder jeden anderen benutzerdefinierten Vorgang. Der neue Operator wird mit der Syntax := aufgerufen, ist aber als Assign definiert:

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

Bei der Operatordefinition müssen genaue Regel eingehalten werden, wie z. B., dass der erste Parameter ein Referenzparameter und der zweite ein per Referenz übergebener var- oder const-Parameter ist. Wenn Sie diese Regeln nicht einhalten, gibt der Compiler Fehlermeldungen wie die folgenden aus:

[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

Das folgende Codefragment ruft den Operator "Assign" auf:

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

Der Operator "Assign" wird zusammen mit den Zuweisungsvorgängen wie im obigen Beispiel verwendet und auch, wenn Sie mit einer Zuweisung eine Inline-Variable initialisieren (in diesem Fall wird der Standardkonstruktor nicht aufgerufen):

 var my4 := my1;

Kopierkonstruktor

Bei der Übergabe eines Record-Parameters oder dem Erstellen eines neuen Records auf der Grundlage eines vorhandenen können Sie einen Kopierkonstruktor definieren: ein Konstruktor, der einen Record desselben Typs als Parameter übernimmt. Falls auch ein Standardkonstruktor vorhanden sein soll, müssen Sie ihn mit der Direktive overload kennzeichnen:

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

Wenn Sie jetzt eine Methode oder Prozedur mit einem regulären Wertparameter (nicht übergeben von const oder var) definieren, verwendet sie beim ihrem Aufruf den Kopierkonstruktor und keinen Zuweisungsaufruf:

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

Beachten Sie, dass auch der Destroy-Destruktor am Ende der Prozedur aufgerufen wird. Eine andere Möglichkeit, den Kopierkonstruktor aufzurufen, ist die Verwendung der folgenden Inline-Variablendeklaration:

 var my3 := TMyRecord.Create (my1);