Delphi'中如何以及何时引用变量;捕获了哪些匿名方法?
这是因为,特别是大卫对巴里问题的评论。因为我没有一个博客可以发布这篇文章,所以我将在这里问这个问题,并回答它 问题:在Delphi的匿名方法中何时以及如何引用变量 例如:Delphi'中如何以及何时引用变量;捕获了哪些匿名方法?,delphi,delphi-2010,anonymous-methods,Delphi,Delphi 2010,Anonymous Methods,这是因为,特别是大卫对巴里问题的评论。因为我没有一个博客可以发布这篇文章,所以我将在这里问这个问题,并回答它 问题:在Delphi的匿名方法中何时以及如何引用变量 例如: procedure ProcedureThatUsesAnonymousMethods; var V: string; F1: TFunc<string>; F2: TFunc<string>; begin F1 := function: string begin
procedure ProcedureThatUsesAnonymousMethods;
var V: string;
F1: TFunc<string>;
F2: TFunc<string>;
begin
F1 := function: string
begin
Result := V; // references local variable
end
V := '1';
F2 := function: string
begin
Result := V;
end
V := '2';
ShowMessage(F1);
ShowMessage(F2);
end;
使用匿名方法的过程;
变量V:字符串;
F1:TFunc;
F2:TFunc;
开始
F1:=函数:字符串
开始
结果:=V;//引用局部变量
结束
V:='1';
F2:=函数:字符串
开始
结果:=V;
结束
V:='2';
ShowMessage(F1);
ShowMessage(F2);
结束;
两个
ShowMessage
都将显示2
。为什么?如何捕获V
以及何时捕获?当您有一个类似问题中的函数,其中有一个匿名方法访问局部变量时,Delphi会创建一个TInterfacedObject子体,该子体将所有基于堆栈的变量捕获为自己的公共变量。使用Barry的技巧来实现TObject和一点RTTI,我们可以看到整个过程正在运行
实现背后的神奇代码可能如下所示:
// Magic object that holds what would normally be Stack variables and implements
// anonymous methods.
type ProcedureThatUsesAnonymousMethods$ActRec = class(TInterfacedObject)
public
V: string;
function AnonMethodImp: string;
end;
// The procedure with all the magic brought to light
procedure ProcedureThatUsesAnonymousMethods;
var MagicInterface: IUnknown;
F1: TFunc<string>;
F2: TFunc<string>;
begin
MagicInterface := ProcedureThatUsesAnonymousMethods$ActRec.Create;
try
F1 := MagicInterface.AnonMethod;
MagicInterface.V := '1';
F2 := MagicInterface.SomeOtherAnonMethod;
MagicInterface.V := '2';
ShowMessage(F1);
ShowMessage(F2);
finally MagicInterface := nil;
end;
end;
在SO发帖对社区也更有帮助。(当然,你在这里发帖会获得更多的声誉!:)嗯。。。如果函数/过程不属于对象,它们是否被称为“方法”?您使用的是哪个delphi版本?@Andreas,只有当它们属于类时,我才称它们为“方法”。我只是重新阅读了问题和答案,如果我真的把两者混在一起,我就看不出其中的混淆:——(我在想
ProcedureThatUsesAnonymousMethods;
我到目前为止从未想过这一点,但即使F1
和F2
都是匿名的,它们是匿名的方法吗?
unit Unit25;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Rtti;
type
TForm25 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
ClassVar: string;
public
end;
var
Form25: TForm25;
implementation
{$R *.dfm}
procedure TForm25.Button1Click(Sender: TObject);
var F1: TFunc<string>;
F2: TFunc<string>;
OnStack: string;
i: IInterface;
o: TObject;
RC: TRttiContext;
R: TRttiType;
RF: TRttiField;
begin
// This anonymous method references a member field of the TForm class
F1 := function :string
begin
Result := ClassVar;
end;
i := PUnknown(@F1)^;
o := i as TObject;
ShowMessage(IntToStr(Integer(o))); // I'm looking at the pointer to see if it's the same instance as the one for the other Anonymous method
// This anonymous method references a stack variable
F2 := function :string
begin
Result := OnStack;
end;
i := PUnknown(@F2)^;
o := i as TObject;
ShowMessage(IntToStr(Integer(o)));
ShowMessage(o.ClassName + ': ' + o.ClassType.ClassParent.ClassName);
RC.Create;
try
R := RC.GetType(o.ClassType);
for RF in R.GetFields do
ShowMessage(RF.Name + ':' + RF.FieldType.Name);
finally RC.Free;
end;
ClassVar := 'Class Var';
OnStack := 'On Stack';
ShowMessage(F1);
ShowMessage(F2);
end;
end.