How to check if two method references are referencing same method?
anonymous-methods, delphi, method-reference
Solution
This is not as easy as it might seem.
To understand why this happens you need to understand how assigning to a method reference is performed by the compiler.
The code you wrote is basically translated into this by the compiler:
Handlers.Add(procedure begin TestProc; end);
Handlers.Remove(procedure begin TestProc; end);
Now we have to know that if you have multiple anonymous methods within the same routine they are in fact different anonymous methods even if their code is identical. (see How are anonymous methods implemented under the hood?)
This means that the values passed to `Add` and `Remove` are different even if the code in their bodies is the same - even with hacking around it would require a binary code analysis to determine if the code inside the body is the same.
If you would change the code as follows it would work because then you only have one anonymous method - for this snipped it works but usually you would not add and remove within the exact same routine:
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;
If you want a list where you add and remove event handlers my personal recommendation is to avoid an anonymous method type and use procedure or methods:
type
TEventHandlerA = procedure;
TEventHandlerB = procedure of object;
The decision which one is better is up to you because you know your code better.
Problem
I am trying to make list of event handlers where handler is method reference. To delete specific handler i need to find it in the list. But how can i compare code address of two method references? ``` 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; ``` Default comparer of TList<> doesn't compare method references properly. How can i compare them? Is there structure similar to TMethod but for method references?