我很想知道为什么Delphi将记录类型属性视为只读:
TRec = record
A : integer;
B : string;
end;
TForm1 = class(TForm)
private
FRec : TRec;
public
procedure DoSomething(ARec: TRec);
property Rec : TRec read FRec write FRec;
end;
Run Code Online (Sandbox Code Playgroud)
如果我尝试为Rec属性的任何成员赋值,我将得到"左侧无法分配"错误:
procedure TForm1.DoSomething(ARec: TRec);
begin
Rec.A := ARec.A;
end;
Run Code Online (Sandbox Code Playgroud)
允许对底层字段执行相同操作:
procedure TForm1.DoSomething(ARec: TRec);
begin
FRec.A := ARec.A;
end;
Run Code Online (Sandbox Code Playgroud)
这种行为有什么解释吗?
All*_*uer 35
由于"Rec"是一个属性,编译器对它的处理方式略有不同,因为它必须首先评估属性decl的"读取".考虑一下,这在语义上等同于您的示例:
...
property Rec: TRec read GetRec write FRec;
...
Run Code Online (Sandbox Code Playgroud)
如果你这样看,你可以看到第一个引用"Rec"(在点'.'之前),必须调用GetRec,它将创建Rec的临时本地副本.这些临时设计在设计上是"只读的".这就是你遇到的.
你可以在这里做的另一件事是将记录的各个字段作为包含类的属性分解:
...
property RecField: Integer read FRec.A write FRec.A;
...
Run Code Online (Sandbox Code Playgroud)
这将允许您通过属性直接分配给类实例中该嵌入记录的字段.
Too*_*the 20
是的,这是一个问题.但是使用记录属性可以解决问题:
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;
Run Code Online (Sandbox Code Playgroud)
这编译和工作没有问题.
veh*_*rix 10
我经常使用的解决方案是将属性声明为指向记录的指针.
type
PRec = ^TRec;
TRec = record
A : integer;
B : string;
end;
TForm1 = class(TForm)
private
FRec : TRec;
function GetRec: PRec;
procedure SetRec(Value: PRec);
public
property Rec : PRec read GetRec write SetRec;
end;
implementation
function TForm1.GetRec: PRec;
begin
Result := @FRec;
end;
procedure TForm1.SetRec(Value: PRec);
begin
FRec := Value^;
end;
Run Code Online (Sandbox Code Playgroud)
这样,直接分配Form1.Rec.A := MyInteger
将起作用,但也Form1.Rec := MyRec
可以按预期将所有值复制MyRec
到FRec
字段中.
这里唯一的缺陷是,当你想要实际检索要使用的记录副本时,你将不得不这样做 MyRec := Form1.Rec^