这一点变得复杂,因为
OnResize
是一个属性而不是一个变量。而且很难直接引用方法,否则编译器会认为你要调用该方法。这就是Pascal的方便之处,允许您在不使用括号的情况下调用过程的缺点所在。
所有这些使得在一行代码中完成此操作相当困难。据我所见,您需要像这样做:
destructor TSomeControl.Destroy;
var
Method1, Method2: TNotifyEvent;
begin
if Assigned(FPanel) then
begin
Method1 := FPanel.OnResize;
Method2 := HandlePanelResize;
if TMethod(Method1) = TMethod(Method2) then
FPanel.OnResize := nil;
end;
FPanel := nil;
inherited;
end;
这依赖于现代 Delphi 中的 TMethod
记录,它包括一个重载的等号运算符来使得 =
测试工作。
如果我需要多次执行此操作,我会将其封装成通用方法。可能看起来像这样:
type
TEventComparer = class
class function Equal<T>(const lhs, rhs: T): Boolean; static;
end;
class function TEventComparer.Equal<T>(const lhs, rhs: T): Boolean;
begin
Assert(SizeOf(T)=SizeOf(TMethod));
Result := TMethod((@lhs)^)=TMethod((@rhs)^);
end;
您需要这样调用它:
destructor TSomeControl.Destroy;
begin
if Assigned(FPanel) and TEventComparer.Equal<TNotifyEvent>(FPanel.OnResize,
HandlePanelResize) then
FPanel.OnResize := nil;
FPanel := nil;
inherited;
end;
这件事突出了一个问题,那就是可用的通用约束并不允许您将类型限制为方法指针。因此,需要进行基本的检查,即 T
的大小与方法的大小相同。但是,这并不能提供太多的安全性。您可以传递 Int64
或者 Double
来调用此方法。我很想看到有人能否提出更简洁的方案。