2009-04-21 13 views
13

estoy usando la sobrecarga de operadores para los registros en Delphi 2006. (Por favor, no responder a esta pregunta diciendo que no me.)¿Cómo puedo definir operadores de conversión implícitos para registros mutuamente dependientes?

Tengo dos tipos de registro con el operador implícita sobrecargado. Ambos están solo en la implementación del módulo, no expuestos a través de la interfaz.

Mi problema es que, ahora que son mutuamente dependientes, no sé cómo reenviar declarar el segundo tipo al compilador. Sé cómo hacer esto con funciones, procedimientos y clases, pero no con registros.

Aquí es un ejemplo simplificado de lo que yo estoy tratando de hacer:

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

Si cada tipo puede convertir implícitamente el mismo que el otro tipo, es posible que desee volver a examinar si realmente necesita dos tipos separados . –

+0

@Rob: es bastante posible. Recientemente me encontré con esta misma situación cuando tenía dos tipos diferentes de vectores, uno compuesto por enteros y uno de flotadores. Necesita ambos tipos para cosas diferentes, pero desea que los dos sean mutuamente compatibles. La solución fue básicamente la que publicaste. –

+1

Los tipos no son tan simples. Uno lleva estadísticas de resumen sobre el otro. Se usan para agrupar lógicamente datos que se transmiten a otros lugares. [vuelto a publicar para tratar de deshacerse del exceso de espacio en blanco.] –

Respuesta

13

No se puede tener declaraciones adelantadas de los tipos de registro. Definir tanto Implicit operadores en el segundo tipo:

type 
    TMyRec1 = record 
    Field1 : Integer; 
    end; 

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

Citando de the help: deben proporcionarse

conversiones implícitas sólo cuando es absolutamente necesario, y la reflexividad debe ser evitado. Lo mejor es dejar que el tipo B se convierta implícitamente en el tipo A, y que el tipo A no tenga conocimiento del tipo B (o viceversa).

+0

Gracias Rob. Una solución obvia, supongo, pero todas son cuando lo sabes. ¿Por qué dices que se debe evitar la conversión implícita? –

+0

* I * no dijo que deba evitarse. Estaba citando la documentación. Pero como usted preguntó, la conversión implícita puede hacer que el código sea más difícil de leer; es más difícil notar que ocurre una conversión cuando no hay nada que llame la atención. Solo usaría una función común para convertir de un tipo a otro. O podría usar el operador Explícito en su lugar. –

+0

Gracias. Debería leer más cuidadosamente. Le eché un vistazo al bit que dice 'citando de la ayuda'.Sí, estoy un poco nervioso acerca de la sobrecarga del operador y las conversiones implícitas también, pero lo intento en un pequeño caso para ver cómo funciona. Curiosamente, algunos de los principales problemas de rendimiento que tuve que corregir han sido la conversión implícita de los tipos numéricos y de cadena estándar. –

3

Usted puede ser capaz de hacer esto con ayudantes de registro.

A continuación se muestra lo que he hecho recientemente para evitar la imposibilidad de tener una declaración de registro forward record.

Utiliza la construcción record helper, que, como implicit type casts, tiene inconvenientes también.
El más importante es que solo se aplicará el record helper más cercano para un tipo particular record.

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; 

que lo utilice como esto:

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

--jeroen

+0

Gracias. Le daré un vistazo. No estaba al tanto de la construcción de 'registro ayudante'. –

+1

Se introdujo silenciosamente en Delphi 2006 para Win32 y .NET. Los asistentes de clase se introdujeron en Delphi 2005 para Win32 y la primera versión .NET de Delphi (un número de versión que muchas personas no desean que se les recuerde). –

Cuestiones relacionadas