delphi – 如何检查两个方法引用是否引用相同的方法?

前端之家收集整理的这篇文章主要介绍了delphi – 如何检查两个方法引用是否引用相同的方法?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试列出处理程序是方法引用的事件处理程序。
删除特定的处理程序,我需要在列表中找到它。
但是如何比较两个方法引用的代码地址?
  1. type
  2. TEventHandler = reference to procedure;
  3.  
  4. procedure TestProc;
  5. begin
  6. end;
  7.  
  8. procedure TForm26.FormCreate(Sender: TObject);
  9. var
  10. Handlers: TList<TEventHandler>;
  11. begin
  12. Handlers := TList<TEventHandler>.create;
  13. try
  14. Handlers.Add(TestProc);
  15. Handlers.Remove(TestProc); { doesn't work }
  16. Assert(Handlers.Count=0); { fails }
  17. Assert(Handlers.IndexOf(TestProc)>=0); { fails }
  18. finally
  19. FreeAndNil(Handlers);
  20. end;
  21. end;

TList的默认比较器不正确比较方法参考。
我如何比较他们?是否有类似于TMethod的结构,但是对于方法引用?

解决方法

这不像看起来那么容易。

要了解为什么会发生这种情况,您需要了解编译器如何执行方法引用的分配。

您编写的代码基本上由编译器翻译成:

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

现在我们必须知道,如果您在同一个例程中有多个匿名方法,那么即使他们的代码是相同的,它们实际上也是不同的匿名方法。 (见How are anonymous methods implemented under the hood?)

这意味着传递给“添加删除”的值即使其身体中的代码是相同的,即使是黑客也需要二进制代码分析来确定正文中的代码是否相同。

如果你改变代码如下,它将工作,因为你只有一个匿名方法 – 为这个剪辑它的工作,但通常你不会添加删除在完全相同的例程:

  1. var
  2. Handlers: TList<TEventHandler>;
  3. Handler: TEventHandler;
  4. begin
  5. Handlers := TList<TEventHandler>.create;
  6. try
  7. Handler := TestProc;
  8. Handlers.Add(Handler);
  9. Handlers.Remove(Handler);
  10. Assert(Handlers.Count=0);
  11. finally
  12. FreeAndNil(Handlers);
  13. end;
  14. end;

如果您想要添加删除事件处理程序的列表,我的个人建议是避免匿名方法类型并使用过程或方法

  1. type
  2. TEventHandlerA = procedure;
  3. TEventHandlerB = procedure of object;

最好的决定取决于你,因为你的代码更好。

猜你在找的Delphi相关文章