gpt4 book ai didi

delphi - 返回带有接口(interface)字段的记录的函数

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

询问后this question about interface fields in records我假设以下内容可行(注意断言):

type
TRec <T> = record
Intf : IInterface;
end;

TTestClass = class
public
function ReturnRec : TRec <Integer>;
end;

// Implementation
function TTestClass.ReturnRec : TRec <Integer>;
begin
Assert (Result.Intf = nil); // Interface field in record should be initialized!
Result.Intf := TInterfacedObject.Create;
end;

我使用以下代码对此进行了测试:

  for I := 1 to 1000 do
Rec := Test.ReturnRec;

断言失败!

我的错误在哪里?什么假设是错误的?

最佳答案

功能

function ReturnRec: TRec<Integer>;

语义上等于过程

procedure ReturnRec(var Result: TRec<Integer>);

[我很确定来自 Embarcadero 的人,可能是 Barry Kelly 或 Alan Bauer 在某处说过这一点,但我目前找不到引用资料。]

在第二种情况下,编译器假定记录在传递给 ReturnRec 之前将被初始化(如果需要),并且不会在 ReturnRec 内为 rec 创建任何初始化代码。我假设第一个示例采用编译器内相同的代码路径,这就是结果未初始化的原因。

无论如何,解决方案很简单:

function TTestClass.ReturnRec : TRec <Integer>;
begin
Result.Intf := TInterfacedObject.Create;
end;

假设编译器知道它在做什么并分配接口(interface),一切都会正常工作。

编辑

您遇到的问题是由“for”循环引起的。您的代码

for I := 1 to 1000 do
Rec := Test.ReturnRec;

被编译成这样的东西:

var
result: TRec<Integer>;

Initialize(result);
for I := 1 to 1000 do begin
Test.ReturnRec(result);
rec := result;
end;

这就是为什么您要重复使用相同的记录,这就是为什么 Result.Intf 仅在第一次时未初始化。

编辑2

您可以通过将 t.ReturnRec 调用从循环移出到单独的方法中来欺骗编译器。

procedure GetRec(t: TTest; var rec: TRec);
begin
rec := t.ReturnRec;
end;

for i := 1 to 1000 do
GetRec(t, rec);

现在,隐藏的结果变量位于 GetRec 过程中,并在每次调用 GetRec 时进行初始化。

关于delphi - 返回带有接口(interface)字段的记录的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8518992/

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