gpt4 book ai didi

Delphi引用程序怪异

转载 作者:行者123 更新时间:2023-12-03 15:47:30 24 4
gpt4 key购买 nike

在 Delphi 中,您显然可以将整个方法调用链分配给单个变量:

program What;
{$APPTYPE CONSOLE}

type
TProc = reference to procedure();

TRecord = record
procedure MethodOfRecord();
end;

procedure TRecord.MethodOfRecord();
begin
WriteLn('MethodOfRecord finished');
end;

function MakeRecord(): TRecord;
begin
WriteLn(' MakeRecord finished');
end;

var
proc: TProc;
begin
proc := MakeRecord().MethodOfRecord;
proc();
proc();
proc();
end.

在此代码中,我创建一个匿名 TRecord,将其方法 TRecord.MethodOfRecord 分配给对过程的引用,然后调用它3次。

问题:MakeRecord 会被调用多少次?

答案:3次:

    MakeRecord finished
MethodOfRecord finished
MakeRecord finished
MethodOfRecord finished
MakeRecord finished
MethodOfRecord finished

每次我调用proc时,它都会先调用MakeRecord。这看起来很奇怪。为什么会出现这种情况?我预计它只会被调用一次。是因为匿名吗?当然,如果我给 TRecord 一个名称,它只会被调用一次:

var
proc: TProc;
rec: TRecord;
begin
rec := MakeRecord();
proc := rec.MethodOfRecord;
proc();
proc();
proc();
end.

此输出:

    MakeRecord finished
MethodOfRecord finished
MethodOfRecord finished
MethodOfRecord finished

有人可以解释一下这种行为背后的逻辑吗?这是否记录在某处?

这是 Embarcadero® Delphi 10.3。

更新:

这不仅适用于对 procedure() 的引用,还适用于对任何可以接受参数和返回值的函数的引用,例如使用 TProc = 对函数的引用:字符串):字符串;.

program What;
{$APPTYPE CONSOLE}

uses System.SysUtils;

type
TProc = reference to function(s: string): string;

TRecord = record
FirstHalf: string;
function Combine(secondHalf: string): string;
end;

function TRecord.Combine(secondHalf: string): string;
begin
Result := Format('%s + %s', [FirstHalf, secondHalf]);
WriteLn(Format(' Combine finished with secondHalf = %s', [secondHalf]));
end;

function MakeRecord(firstHalf: string): TRecord;
begin
Result.FirstHalf := firstHalf;
WriteLn(Format('MakeRecord finished with firstHalf = %s', [firstHalf]));
end;

var
proc: TProc;
msg: string;
begin
proc := MakeRecord(msg).Combine;
msg := 'A';
WriteLn(proc('a'));
msg := 'B';
WriteLn(proc('b'));
msg := 'C';
WriteLn(proc('c'));
end.

输出:

MakeRecord finished with  firstHalf = A
Combine finished with secondHalf = a
A + a
MakeRecord finished with firstHalf = B
Combine finished with secondHalf = b
B + b
MakeRecord finished with firstHalf = C
Combine finished with secondHalf = c
C + c

最佳答案

proc := MakeRecord().MethodOfRecord;

这里proc是一个匿名方法,但MethodOfRecord不是,它是一个普通的过程。您可能预计会出现编译错误,但编译器会在后台为您完成一些工作。它将你的代码变成这样:

proc := 
procedure
begin
MakeRecord().MethodOfRecord;
end;

现在右侧是一个匿名方法,您可以看到为什么您的程序会这样做。

如果您不希望在每次调用时创建新记录,则需要为要使用的记录实例声明一个局部变量。

关于Delphi引用程序怪异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61980648/

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