"Reference to" 在 Delphi 中究竟做了什么?
What does "Reference to" do exactly in Delphi?
在 Anonymous Methods in Delphi 阅读文档时,我开始怀疑。我一直使用这样的东西:
type TMathFn = Function(A, B: Integer): Integer;
var fn: TMathFn;
一直对我有用。但是这个文件告诉我用这个代替:
type TMathFn = Reference to Function(A, B: Integer): Integer;
var fn: TMathFn;
因为我从 1994 年到 2010 年一直在 Delphi 开发,所以我对这个“参考”部分有点陌生。不过,这两种选择似乎都一样有效。所以...
它们相同吗?
"REFERENCE TO" 允许匿名方法(PROCEDUREs/FUNCTIONs 的内联定义),它可以捕获上下文(例如局部变量,它们被捕获为引用,即如果您在之后更改变量捕获,它是捕获的修改值,见下文)。
TYPE TMyProc = REFERENCE TO PROCEDURE(CONST S : STRING);
PROCEDURE Information(CONST S : STRING);
BEGIN
MessageDlg(S,mtInformation,[mbOK],0)
END;
PROCEDURE RunProc(P : TMyProc ; CONST S : STRING);
BEGIN
P(S)
END;
PROCEDURE A(B,C : INTEGER);
VAR
D : INTEGER;
P : TMyProc;
BEGIN
D:=3;
// D is 3 at the time of capture
P:=PROCEDURE(CONST S : STRING)
BEGIN
Information(S+': '+IntToStr(D)+' -> '+IntToStr(B))
END;
// D is now 4 - and is reflected in the captured routine, as
// the capture is done by REFERENCE and not by VALUE.
INC(D);
RunProc(P,'Hello')
END;
BEGIN
A(2,3)
END.
将在消息框中显示“你好:4 -> 2”。
P 的上述定义“捕获”(包括)变量 D 和 B,这样即使您将它传递给另一个函数,在这些变量不存在的地方,您仍然可以访问它们。
对于普通的 PROCEDURE [OF OBJECT] 类型,这(几乎)是不可能的,因为它们无法访问在执行时声明的局部变量。
不,它们不相同。
不同的是
TMathFn = function(A, B: Integer): Integer;
是普通函数,
TMathMethod = function(A, B: Integer): Integer of object;
是方法,
TMathAnonMethod = reference to function(A, B: Integer): Integer;
是匿名方法,但也可以将普通函数或方法赋值给该类型的变量
所以,例如,如果
type
TMathFn = function(A, B: Integer): Integer;
TMathMethod = function(A, B: Integer): Integer of object;
TMathAnonMethod = reference to function(A, B: Integer): Integer;
function Test(A, B: Integer): Integer;
begin
Result := A + B;
end;
type
TTestClass = class
function Test(A, B: Integer): Integer;
end;
{ TTestClass }
function TTestClass.Test(A, B: Integer): Integer;
begin
Result := A + B;
end;
则适用以下内容:
procedure TForm1.FormCreate(Sender: TObject);
var
T: TTestClass;
F: TMathFn;
M: TMathMethod;
AM: TMathAnonMethod;
begin
T := TTestClass.Create;
try
F := Test; // compiles
F := T.Test; // doesn't compile
F := function(A, B: Integer): Integer
begin
Result := A + B;
end; // doesn't compile
M := Test; // doesn't compile
M := T.Test; // compiles
M := function(A, B: Integer): Integer
begin
Result := A + B;
end; // doesn't compile
AM := Test; // compiles
AM := T.Test; // compiles
AM := function(A, B: Integer): Integer
begin
Result := A + B;
end; // compiles
finally
T.Free;
end;
end;
在幕后,您可能已经知道,F
只是一个(函数)指针,而 M
是一个 method pointer。另一方面,匿名方法有一个更复杂的 interface-based 实现,这允许它们所有的魔法(比如变量捕获)。
在 Anonymous Methods in Delphi 阅读文档时,我开始怀疑。我一直使用这样的东西:
type TMathFn = Function(A, B: Integer): Integer;
var fn: TMathFn;
一直对我有用。但是这个文件告诉我用这个代替:
type TMathFn = Reference to Function(A, B: Integer): Integer;
var fn: TMathFn;
因为我从 1994 年到 2010 年一直在 Delphi 开发,所以我对这个“参考”部分有点陌生。不过,这两种选择似乎都一样有效。所以...
它们相同吗?
"REFERENCE TO" 允许匿名方法(PROCEDUREs/FUNCTIONs 的内联定义),它可以捕获上下文(例如局部变量,它们被捕获为引用,即如果您在之后更改变量捕获,它是捕获的修改值,见下文)。
TYPE TMyProc = REFERENCE TO PROCEDURE(CONST S : STRING);
PROCEDURE Information(CONST S : STRING);
BEGIN
MessageDlg(S,mtInformation,[mbOK],0)
END;
PROCEDURE RunProc(P : TMyProc ; CONST S : STRING);
BEGIN
P(S)
END;
PROCEDURE A(B,C : INTEGER);
VAR
D : INTEGER;
P : TMyProc;
BEGIN
D:=3;
// D is 3 at the time of capture
P:=PROCEDURE(CONST S : STRING)
BEGIN
Information(S+': '+IntToStr(D)+' -> '+IntToStr(B))
END;
// D is now 4 - and is reflected in the captured routine, as
// the capture is done by REFERENCE and not by VALUE.
INC(D);
RunProc(P,'Hello')
END;
BEGIN
A(2,3)
END.
将在消息框中显示“你好:4 -> 2”。
P 的上述定义“捕获”(包括)变量 D 和 B,这样即使您将它传递给另一个函数,在这些变量不存在的地方,您仍然可以访问它们。
对于普通的 PROCEDURE [OF OBJECT] 类型,这(几乎)是不可能的,因为它们无法访问在执行时声明的局部变量。
不,它们不相同。
不同的是
TMathFn = function(A, B: Integer): Integer;
是普通函数,
TMathMethod = function(A, B: Integer): Integer of object;
是方法,
TMathAnonMethod = reference to function(A, B: Integer): Integer;
是匿名方法,但也可以将普通函数或方法赋值给该类型的变量
所以,例如,如果
type
TMathFn = function(A, B: Integer): Integer;
TMathMethod = function(A, B: Integer): Integer of object;
TMathAnonMethod = reference to function(A, B: Integer): Integer;
function Test(A, B: Integer): Integer;
begin
Result := A + B;
end;
type
TTestClass = class
function Test(A, B: Integer): Integer;
end;
{ TTestClass }
function TTestClass.Test(A, B: Integer): Integer;
begin
Result := A + B;
end;
则适用以下内容:
procedure TForm1.FormCreate(Sender: TObject);
var
T: TTestClass;
F: TMathFn;
M: TMathMethod;
AM: TMathAnonMethod;
begin
T := TTestClass.Create;
try
F := Test; // compiles
F := T.Test; // doesn't compile
F := function(A, B: Integer): Integer
begin
Result := A + B;
end; // doesn't compile
M := Test; // doesn't compile
M := T.Test; // compiles
M := function(A, B: Integer): Integer
begin
Result := A + B;
end; // doesn't compile
AM := Test; // compiles
AM := T.Test; // compiles
AM := function(A, B: Integer): Integer
begin
Result := A + B;
end; // compiles
finally
T.Free;
end;
end;
在幕后,您可能已经知道,F
只是一个(函数)指针,而 M
是一个 method pointer。另一方面,匿名方法有一个更复杂的 interface-based 实现,这允许它们所有的魔法(比如变量捕获)。