delphi – 方法的默认通用比较器返回不正确的结果
发布时间:2020-12-15 04:17:00 所属栏目:大数据 来源:网络整理
导读:在使用建议的 multicast delegate方法来响应 Signals and slots implementation in Delphi问题时,代码无法添加多个事件处理程序. 问题与在TDelegateImpl T .Add()中向事件列表添加方法有关,TList T .IndexOf方法使用Compare方法查找现有方法,结果始终为0 –
在使用建议的
multicast delegate方法来响应
Signals and slots implementation in Delphi问题时,代码无法添加多个事件处理程序.
问题与在TDelegateImpl< T> .Add()中向事件列表添加方法有关,TList< T> .IndexOf方法使用Compare方法查找现有方法,结果始终为0 – 表示Left和Right是同样适用于TMethod. Equals方法使用TMethod类型转换并显式比较TMethod.Code和TMethod.Data,其中Compare转换为始终相同的地址. 为什么在TList< T> .IndexOf中使用Compare而不是Equals? 解决方法
问题是这个功能:
function Compare_Method(Inst: PSimpleInstance; const Left,Right: TMethodPointer): Integer; begin if PInt64(@Left)^ < PInt64(@Right)^ then Result := -1 else if PInt64(@Left)^ > PInt64(@Right)^ then Result := 1 else Result := 0; end; 这将方法与Int64进行比较.这不起作用,因为@可能在这里没有效果. CPU视图确认了这一点: System.Generics.Defaults.pas.1089: begin 00447690 55 push ebp 00447691 8BEC mov ebp,esp System.Generics.Defaults.pas.1090: if PInt64(@Left)^ < PInt64(@Right)^ then 00447693 8B4510 mov eax,[ebp+$10] 00447696 8B5004 mov edx,[eax+$04] 00447699 8B00 mov eax,[eax] 0044769B 8B4D08 mov ecx,[ebp+$08] 0044769E 3B5104 cmp edx,[ecx+$04] 004476A1 7506 jnz $004476a9 004476A3 3B01 cmp eax,[ecx] 004476A5 7309 jnb $004476b0 004476A7 EB02 jmp $004476ab 004476A9 7D05 jnl $004476b0 System.Generics.Defaults.pas.1091: Result := -1 004476AB 83C8FF or eax,-$01 004476AE EB21 jmp $004476d1 System.Generics.Defaults.pas.1092: else if PInt64(@Left)^ > PInt64(@Right)^ then 004476B0 8B4510 mov eax,[ebp+$10] etc... 要将两个TM方法作为Int64进行比较,这应该是: System.Generics.Defaults.pas.1090: if PInt64(@Left)^ < PInt64(@Right)^ then 00447693 8B4510 lea eax,[ebp+$10] // not MOV 00447696 8B5004 mov edx,[eax] 0044769B 8B4D08 lea ecx,[ebp+$08] // not MOV 0044769E 3B5104 cmp edx,[ecx] etc... 这清楚地表明PInt64(@Left)^被解释为PInt64(左)^. 对于Delphi 32和Delphi 64,正确的实现应该或多或少看起来像这样: function Compare_Method(Inst: PSimpleInstance; const Left,Right: TMethodPointer): Integer; var LCode,LData: PByte; RCode,RData: PByte; begin LCode := PByte(TMethod(Left).Code); LData := PByte(TMethod(Left).Data); RCode := PByte(TMethod(Right).Code); RData := PByte(TMethod(Right).Data); if LData < RData then Result := -1 else if LData > RData then Result := 1 else if LCode < RCode then Result := -1 else if LCode > RCode then Result := 1 else Result := 0; end; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |