gpt4 book ai didi

Delphi,记录类型属性,记录字段赋值: Assignment to local copy of record expected

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

问题结束 “Left side cannot be assigned to” for record type properties in Delphi ,有an answer Toon Krijthe 演示了如何通过使用记录声明中的属性来完成对记录属性字段的分配。为了方便引用,这里是 Toon Krijthe 发布的代码片段。

type
TRec = record
private
FA : integer;
FB : string;
procedure SetA(const Value: Integer);
procedure SetB(const Value: string);
public
property A: Integer read FA write SetA;
property B: string read FB write SetB;
end;

procedure TRec.SetA(const Value: Integer);
begin
FA := Value;
end;

procedure TRec.SetB(const Value: string);
begin
FB := Value;
end;

TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
FRec : TRec;
public
property Rec : TRec read FRec write FRec;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Rec.A := 21;
Rec.B := 'Hi';
end;

我很清楚为什么在 vcldeveloper 的原始代码中没有记录中的 setter 时会出现“左侧无法分配给”错误。我也清楚为什么分配 Rec.A := 21; 没有出现错误。如果为属性 TRec.A 定义了 setter就像上面代码的情况一样。

我不明白的是为什么分配 Rec.A := 21;将值 21 分配给字段 FRec.FATForm1 。我预计该值会分配给字段 FA FRec本地临时副本但不是FRec.FA本身。谁能解释一下这里发生的事情吗?

最佳答案

这是一个很好的问题!

您看到的行为是属性实现细节的结果。对于直接字段属性 getter 和函数属性 getter ,编译器实现属性的方式有所不同。

当你写的时候

Rec.A := 21;

编译器看到Rec并知道它是一个属性。由于 getter 是直接字段 getter,编译器只需将 Rec 替换为 FRec 并编译代码,就像您编写的一样

FRec.A := 21;

然后编译器遇到 A 属性并使用 setter 方法,因此您的赋值变为

FRec.SetA(21);

因此出现了您观察到的行为。

假设您使用的是函数 getter,而不是直接字段 getter

property Rec: TRec read GetRec;
....
function TForm1.GetRec: TRec;
begin
Result := FRec;
end;

在这种情况下的处理

Rec.A := 21;

改变。相反,编译器声明一个隐式局部变量,代码编译如下:

var
__local_rec: TRec;
....
__local_rec := GetRec;
__local_rec.A := 21;
<小时/>

对我来说,很明显,这样的程序的行为不应该取决于属性 getter 是直接字段 getter 还是函数 getter。这似乎是属性功能和增强记录功能之间交互的设计缺陷。

<小时/>

这是一个完整的程序,非常简洁地演示了该问题:

{$APPTYPE CONSOLE}

type
TRec = record
private
FA: Integer;
procedure SetA(const Value: integer);
public
property A: integer read FA write SetA;
end;

procedure TRec.SetA(const Value: integer);
begin
FA := Value;
end;

type
TMyClass = class
private
FRec: TRec;
function GetRec: TRec;
public
property RecDirect: TRec read FRec;
property RecFunction: TRec read GetRec;
end;

var
Obj: TMyClass;

function TMyClass.GetRec: TRec;
begin
Result := FRec;
end;

begin
Obj := TMyClass.Create;
Obj.RecDirect.A := 21;
Writeln(Obj.FRec.FA);

Obj := TMyClass.Create;
Obj.RecFunction.A := 21;
Writeln(Obj.FRec.FA);
end.

输出

210

关于Delphi,记录类型属性,记录字段赋值: Assignment to local copy of record expected,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54999249/

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