我试图列出事件处理程序的列表,其中处理程序是方法参考。要删除特定的处理程序,我需要在列表中找到它。但是,如何比较两个方法引用的代码地址?type TEventHandler = reference to procedure;procedure TestProc;beginend;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;TList 的默认比较器无法正确比较方法引用。我如何比较它们?是否有类似于TMethod的结构,但可供方法参考? 最佳答案 这并不像看起来那样容易。要了解为什么会发生这种情况,您需要了解编译器如何执行分配给方法引用的操作。您编写的代码基本上是由编译器翻译成的:Handlers.Add(procedure begin TestProc; end);Handlers.Remove(procedure begin TestProc; end);现在我们必须知道,如果在同一个例程中有多个匿名方法,那么即使它们的代码相同,它们实际上也是不同的匿名方法。 (请参见How are anonymous methods implemented under the hood?)这意味着即使它们体内的代码相同,传递给Add和Remove的值也有所不同-即使对其进行黑客攻击,也需要进行二进制代码分析才能确定体内的代码是否相同。如果您按照以下方式更改代码,那么它将起作用,因为您只有一个匿名方法-对于此代码段,它可以起作用,但通常不会在完全相同的例程中进行添加和删除: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;如果您想要一个在其中添加和删除事件处理程序的列表,我个人的建议是避免使用匿名方法类型并使用一个或多个过程:type TEventHandlerA = procedure; TEventHandlerB = procedure of object;一个更好的决定取决于您,因为您更了解自己的代码。关于delphi - 如何检查两个方法引用是否引用同一方法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40260923/
10-13 02:14