先贴一小段例子说明这个方法的意义
procedure TForm1.Button1Click(
Sender: TObject);
var
s
: string;
begin
s
:='aa';
//用这句表示s的值经过一个复杂的计算,得出值为aa
timer1.OnTimer:=NotifyEvent(
//给这个TTimer控件指定onTimer事件
procedure(
sender: TObject)
begin
memo1.Lines.Add(s
+ sender.ToString);
//这里使用了s变量,是的,它能“看见”s
end);
end;
如果用别的方法实现上面的功能,s可能会被放在TForm1宝贵的private区域,以让OnTimer事件函数能看到它。而这个方法使你可以连贯的表达你的意图:计算s的值,以某种方式显示它。你不必把这个整体的逻辑划分到两个函数里。
有很多个理由需要把一个匿名过程转换成事件类型,但delphi似乎没有直接提供这个方法,如果有谁知道的话记得告诉我。
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
我自己的实现方法很简单,也很笨,代码很短,贴出来了
_CPack=class(
TComponent)
//这个类不应被客户端看到,它只为NotifyEvent函数使用,所以我在前面加了个下划线。
private
fProc: TProc<TObject>;
procedure event(
sender: TObject);
end;
procedure _CPack.event(
sender: TObject);
begin
fProc(
sender);
end;
function NotifyEvent(p
: TProc<TObject>)
: TNotifyEvent;
var
obj: _CPack;
begin
obj:=_CPack.Create(
Application);
obj.fProc:=p;
Result:=obj.event;
end;
这个实现方法的缺点是每调用一次
NotifyEvent都要产生一个TComponent对象,不过NotifyEvent的调用次数应该是在编译时确定的,所以数量微不足道,如果要在运行时确定,你可以将NotifyEvent的返回值暂存起来用。
这个缺点对我来说不成问题,因为我在写客户端程序时倾向于不释放资源以换取稳定性。
如果你实在在意这个leak,可以给NotifyEvent加一个out id参数,有了id,你就可以控制生存期了。
另一个实现在这里(http://kindi.tistory.com/entry/Using-anonymous-methods-in-method-pointers),韩语的,不知在说什么,但我把它的代码拷出来,上面的示例可以编译通过,也没有我上面方法的问题,但唯一的问题是,它输出的结果是“Timer1”,而不是“aaTimer1",换句话说,s的值不见了。