gpt4 book ai didi

delphi - 匿名方法在幕后是如何实现的?

转载 作者:行者123 更新时间:2023-12-03 14:40:58 25 4
gpt4 key购买 nike

Delphi 是否“实例化”每个匿名方法(如对象)?如果是,Delphi 何时创建此实例,最重要的是,Delphi 何时释放它?

由于匿名方法还会捕获外部变量并延长其生命周期,因此了解这些变量何时从内存中“释放”非常重要。

在另一个匿名方法中声明一个匿名方法可能有哪些缺点。可以循环引用吗?

最佳答案

匿名方法作为接口(interface)实现。本文很好地解释了编译器是如何完成的:Anonymous methods in Delphi: the internals .

本质上,编译器生成的接口(interface)有一个名为 Invoke 的方法,其后面是您提供的匿名方法。

捕获的变量与捕获它们的任何匿名方法具有相同的生命周期。匿名方法是一个接口(interface),其生命周期由引用计数管理。因此,捕获的变量的生命周期与捕获它们的匿名方法一样长。

正如可以使用接口(interface)创建循环引用一样,也同样可以使用匿名方法创建循环引用。这是我可以构建的最简单的演示:

uses
System.SysUtils;

procedure Main;
var
proc: TProc;
begin
proc :=
procedure
begin
if Assigned(proc) then
Beep;
end;
end;

begin
ReportMemoryLeaksOnShutdown := True;
Main;
end.

编译器在幕后创建一个实现匿名方法接口(interface)的隐藏类。该类包含捕获的任何变量作为数据成员。当分配 proc 时,会增加实现实例的引用计数。由于 proc 由实现实例所有,因此该实例已引用其自身。

为了让这一点更清楚一些,该程序提出了相同的问题,但在界面方面进行了重新设计:

uses
System.SysUtils;

type
ISetValue = interface
procedure SetValue(const Value: IInterface);
end;

TMyClass = class(TInterfacedObject, ISetValue)
FValue: IInterface;
procedure SetValue(const Value: IInterface);
end;

procedure TMyClass.SetValue(const Value: IInterface);
begin
FValue := Value;
end;

procedure Main;
var
intf: ISetValue;
begin
intf := TMyClass.Create;
intf.SetValue(intf);
end;

begin
ReportMemoryLeaksOnShutdown := True;
Main;
end.

可以通过显式清除自引用来打破循环。在匿名方法示例中,如下所示:

procedure Main;
var
proc: TProc;
begin
proc :=
procedure
begin
if Assigned(proc) then
Beep;
end;
proc := nil;
end;

接口(interface)变体的等效项是:

procedure Main;
var
intf: ISetValue;
begin
intf := TMyClass.Create;
intf.SetValue(intf);
intf.SetValue(nil);
end;

关于delphi - 匿名方法在幕后是如何实现的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39955052/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com