propiedades propiedad property google crear añadir agregar delphi anonymous-methods method-reference

delphi - propiedad - ¿Cómo verificar si dos referencias de método hacen referencia al mismo método?



search console añadir propiedad (1)

Estoy tratando de hacer una lista de controladores de eventos donde el controlador es referencia de método. Para eliminar un controlador específico, necesito encontrarlo en la lista. Pero, ¿cómo puedo comparar la dirección de código de dos referencias de método?

type TEventHandler = reference to procedure; procedure TestProc; begin end; procedure TForm26.FormCreate(Sender: TObject); var Handlers: TList<TEventHandler>; begin Handlers := TList<TEventHandler>.create; try Handlers.Add(TestProc); Handlers.Remove(TestProc); { doesn''t work } Assert(Handlers.Count=0); { fails } Assert(Handlers.IndexOf(TestProc)>=0); { fails } finally FreeAndNil(Handlers); end; end;

El comparador predeterminado de TList <> no compara correctamente las referencias de los métodos. ¿Cómo puedo compararlos? ¿Existe una estructura similar a TMethod pero para referencias de métodos?


Esto no es tan fácil como podría parecer.

Para comprender por qué sucede esto, debe comprender cómo el compilador realiza la asignación a una referencia de método.

El código que escribiste se traduce básicamente en esto por el compilador:

Handlers.Add(procedure begin TestProc; end); Handlers.Remove(procedure begin TestProc; end);

Ahora debemos saber que si tiene varios métodos anónimos dentro de la misma rutina, en realidad son métodos anónimos diferentes, incluso si su código es idéntico. (ver ¿Cómo se implementan los métodos anónimos bajo el capó? )

Esto significa que los valores pasados ​​a Add y Remove son diferentes, incluso si el código en sus cuerpos es el mismo; incluso con piratearlo, se requeriría un análisis de código binario para determinar si el código dentro del cuerpo es el mismo.

Si cambia el código de la siguiente manera, funcionará porque entonces solo tiene un método anónimo. Para este corte, funciona, pero generalmente no se agregaría ni eliminaría dentro de la misma rutina:

var Handlers: TList<TEventHandler>; Handler: TEventHandler; begin Handlers := TList<TEventHandler>.create; try Handler := TestProc; Handlers.Add(Handler); Handlers.Remove(Handler); Assert(Handlers.Count=0); finally FreeAndNil(Handlers); end; end;

Si desea una lista donde agregue y elimine controladores de eventos, mi recomendación personal es evitar un tipo de método anónimo y utilizar un procedimiento o métodos:

type TEventHandlerA = procedure; TEventHandlerB = procedure of object;

La decisión de cuál es mejor depende de usted porque conoce mejor su código.