Benutzerdefinierte verwaltete Records
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;
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);