2009-04-21 7 views
13

Ich bin mit dem Operator für Aufzeichnungen in Delphi Überlastung 2006. (Bitte verwenden Sie diese Frage nicht beantworten, indem sie mir nicht zu erzählen.)Wie definiere ich implizite Konvertierungsoperatoren für gegenseitig abhängige Datensätze?

Ich habe zwei Satztypen mit dem impliziten Betreiber überlastet. Sie sind beide nur in der Implementierung des Moduls, nicht durch die Schnittstelle ausgesetzt.

Mein Problem ist, jetzt, da sie sich gegenseitig bedingen, ich weiß nicht, wie man den zweiten Typ an den Compiler weiterleiten. Ich weiß, wie man das mit Funktionen, Prozeduren und Klassen macht, aber nicht mit Datensätzen.

Hier ist ein vereinfachtes Beispiel von dem, was ich zu tun versucht:

implementation 

type 
    TMyRec1 = record 
    Field1 : Integer; 
    class operator Implicit(a: TMyRec2): TMyRec1; // <---- Undeclared Identifier here. 
    end; 

    TMyRec2 = record 
    Field2: Integer; 
    class operator Implicit(a: TMyRec1): TMyRec2; 
    end; 

class operator TMyRec1.Implicit(a:TMyRec2): TMyRec1; 
begin 
    Result.Field1 := a.Field2; 
end; 

class operator TMyRec2.Implicit(a:TMyRec2): TMyRec2; 
begin 
    Result.Field2 := a.Field1; 
end; 
+0

Wenn jeder Art implizit selbst auf die andere Art umwandeln können, möchten Sie vielleicht zu überdenken, ob Sie wirklich brauchen zwei getrennte Arten . –

+0

@Rob: Es ist durchaus möglich. Ich bin kürzlich in dieselbe Situation geraten, als ich zwei verschiedene Vektor-Typen hatte, einen aus Integern und einen aus Floats. Sie benötigen beide Typen für verschiedene Dinge, aber Sie möchten, dass die beiden für beide Zuordnungen kompatibel sind. Die Lösung war im Grunde die, die du gepostet hast. –

+1

Die Arten sind nirgends so einfach. Einer trägt zusammenfassende Statistiken über den anderen. Sie werden verwendet, um Daten logisch zu gruppieren, die an anderer Stelle weitergegeben werden. [zurückgeschickt, um überschüssigen Leerraum loszuwerden.] –

Antwort

13

Sie können nicht nach vorne Erklärungen für Datensatztypen haben. Definieren Sie beide Implicit Operatoren in der zweiten Art:

type 
    TMyRec1 = record 
    Field1 : Integer; 
    end; 

    TMyRec2 = record 
    Field2: Integer; 
    class operator Implicit(a: TMyRec2): TMyRec1; 
    class operator Implicit(a: TMyRec1): TMyRec2; 
    end; 

von the help Zitiert:

Implizite Konvertierungen sollten nur vorgesehen werden, wenn unbedingt notwendig, und Reflexivität vermieden werden sollte. Es ist am besten, wenn Typ B implizit in Typ A konvertiert wird und Typ A keine Kenntnis vom Typ B hat (oder umgekehrt).

+0

Danke Rob. Offensichtliche Lösung, denke ich, aber sie alle sind, wenn Sie wissen. Warum sagen Sie, dass implizite Konvertierung vermieden werden sollte? –

+0

* Ich * habe nicht gesagt, dass es vermieden werden sollte. Ich habe die Dokumentation zitiert. Aber da Sie gefragt haben, kann implizite Konvertierung den Code schwerer lesbar machen. Es ist schwieriger, eine Konvertierung zu bemerken, wenn nichts darauf aufmerksam macht. Ich würde nur eine gewöhnliche Funktion verwenden, um von einem Typ in einen anderen zu konvertieren. Oder Sie könnten stattdessen den Operator Explicit verwenden. –

+0

Danke. Ich sollte es genauer lesen. Ich überflog das Stück, das "aus der Hilfe zitierte".Ja, ich bin etwas nervös, wenn es um das Überladen von Operatoren und die impliziten Konvertierungen geht, aber probiere es in einem kleinen Fall aus, um zu sehen, wie es läuft. Lustigerweise waren einige der wichtigsten Leistungsprobleme, die ich beheben musste, die implizite Konvertierung von Standard-numerischen und String-Typen. –

3

Sie könnte der Lage sein, diese Helfer mit Rekord zu tun.

Unten ist, was ich kürzlich getan habe, um die Unmöglichkeit zu arbeiten, eine forward record Aufzeichnungserklärung zu haben.

Es verwendet die record helper Konstruktion, die - wie implicit type casts - auch Nachteile haben.
Der wichtigste ist, dass nur der nächste record helper für einen bestimmten record Typ gilt.

type 
    TIpv4Address = record 
    strict private 
    FAddress: TIpv4Quad; 
    FMask: TIpv4Quad; 
    private 
    class function CreateInternal(const IP_ADDR_STRING: _IP_ADDR_STRING): TIpv4Address; static; 
    public 
    class function Create(const IP_ADDR_STRING: _IP_ADDR_STRING): TIpv4Address; static; 
    class function Count(const IP_ADDR_STRING: _IP_ADDR_STRING): Integer; static; 
    property Address: TIpv4Quad read FAddress; 
    property Mask: TIpv4Quad read FMask; 
    end; 

    TIpv4AddressList = array of TIpv4Address; 

    TIpv4AddressHelper = record helper for TIpv4Address 
    class function CreateList(const IP_ADDR_STRING: _IP_ADDR_STRING): TIpv4AddressList; static; 
    end; 

Sie verwenden es wie folgt aus:

function TAdapterInfo.GetIpAddressList: TIpv4AddressList; 
begin 
    Result := TIpv4Address.CreateList(AdapterInfos.IP_ADAPTER_INFO[Index].IpAddressList); 
end; 

--jeroen

+0

Danke. Ich werde es mir ansehen. Ich war mir nicht bewusst, dass es sich um ein "Datensatzhelfer" -Konstrukt handelte. –

+1

Es wurde in Delphi 2006 für Win32 und .NET automatisch eingeführt. Klassenhelfer wurden in Delphi 2005 für Win32 und der ersten .NET-Version von Delphi eingeführt (eine Versionsnummer, an die viele Leute nicht erinnert werden möchten). –

Verwandte Themen