首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring4d如何使IEvent句柄引用过程?

Spring4d如何使IEvent句柄引用过程?
EN

Stack Overflow用户
提问于 2022-05-13 16:02:27
回答 1查看 95关注 0票数 1

当实现具有以下定义的事件时,Spring4D将添加和调用方法,但在被询问时不会删除处理程序(使用IEvent.Remove(MyProc) ),因为它没有标识它。

代码语言:javascript
复制
  {$M+}
  TaskItemChangeEvent = reference to procedure(const TaskItem: ITaskItem; Event: TTaskListEvent);

下面的内容确实有效,但我不希望被强制绑定到对象上。

代码语言:javascript
复制
  {$M+}
  TaskItemChangeEvent = procedure(const TaskItem: ITaskItem; Event: TTaskListEvent) of Object;

我认为问题是,在TEventBase.Remove中这一行作为对过程的引用不是TMethod吗?

代码语言:javascript
复制
  if TMethod(handlers[i]) = TMethod(handler) then
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-18 11:59:32

原因是编译器可能在添加的位置和删除它们的位置之间创建匿名方法的不同实例。

请查看以下代码:

代码语言:javascript
复制
var
  proc: TProc;

procedure Add(p: TProc);
begin
  proc := p;
end;

procedure Remove(p: TProc);
begin
  Writeln(PPointer(@proc)^ = PPointer(@p)^);
end;

procedure A;
var
  p: TProc;
begin
  p := procedure begin end;
  Add(p);
  Remove(p);
end;

procedure B;
begin
  Add(procedure begin end);
  Remove(procedure begin end);
end;

procedure C;
begin
  Add(A);
  Remove(A);
end;

begin
  A;
  B;
  C;
  Readln;
end.

您将注意到,在BC中,它将打印False,因为传递给AddRemove的两个匿名方法彼此不同。在B中,这一点在C中是显而易见的,但编译器实际上将代码转换为:

代码语言:javascript
复制
procedure C;
begin
  Add(procedure begin A(); end);
  Remove(procedure begin A(); end);
end;

这意味着,如果要将IEvent<>与方法引用类型一起使用并能够删除,则需要保留添加的引用,以便使它们相等,从而能够在调用Remove时找到引用。

TEventBase内部,引用都是作为TMethod处理的,这与此无关--当传递匿名方法时,它将被转换为TMethod。毕竟,匿名方法类型是一个由编译器创建的对象支持的接口,它使进行这种转换成为可能,并且需要保留添加的引用以删除它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72232429

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档