[英]Spring4d How to make IEvent handle reference to procedure?
當使用以下定義實現事件時,Spring4D 將添加和調用方法,但不會在被詢問時刪除處理程序(使用 IEvent<TaskItemChangeEvent>.Remove(MyProc) ),因為它沒有識別它。
{$M+}
TaskItemChangeEvent = reference to procedure(const TaskItem: ITaskItem; Event: TTaskListEvent);
以下確實有效,但我不想被迫綁定到一個對象。
{$M+}
TaskItemChangeEvent = procedure(const TaskItem: ITaskItem; Event: TTaskListEvent) of Object;
我相信問題是 TEventBase.Remove 中的這一行作為對過程的引用不是 TMethod?
if TMethod(handlers[i]) = TMethod(handler) then
原因是編譯器可能會在您添加和刪除它們的位置之間創建匿名方法的不同實例。
看下面的代碼:
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.
您會注意到,在B
和C
中,它將打印False
,因為傳遞給Add
和Remove
的兩個匿名方法彼此不同。 雖然在B
中很明顯,但在C
中並非如此,但編譯器實際上將代碼轉換為:
procedure C;
begin
Add(procedure begin A(); end);
Remove(procedure begin A(); end);
end;
這意味着,如果您想將IEvent<>
與方法引用類型一起使用並能夠刪除,則需要保留您添加的引用,以便它們相等,從而在調用Remove
時能夠找到它們。
事實上,在TEventBase
內部,引用都被處理為TMethod
與此無關 - 當傳遞匿名方法時,它被轉換為TMethod
。 畢竟,匿名方法類型是由編譯器創建的對象支持的接口,這使得進行這種轉換成為可能,並導致必須保留添加的引用以刪除它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.