"Left side cannot be assigned to" for record type properties in Delphi
I'm curious to know why Delphi treats record type properties as read only:
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;
If I try to assign a value to any of the members of Rec property, I'll get "Left side cannot be assigned to" error:
procedure TForm1.DoSomething(ARec: TRec);
begin
Rec.A := ARec.A;
end;
while doing the same with the underlying field is allowed:
procedure TForm1.DoSomething(ARec: TRec);
begin
FRec.A := ARec.A;
end;
Is there any explanation for that behavior?
Since "Rec" is a property, the compiler treats it a little differently because it has to first evaluate the "read" of the property decl. Consider this, which is semantically equivalent to your example:
...
property Rec: TRec read GetRec write FRec;
...
If you look at it like this, you can see that the first reference to "Rec" (before the dot '.'), has to call GetRec, which will create a temporary local copy of Rec. These temporaries are by design "read-only." This is what you're running into.
Another thing you can do here is to break out the individual fields of the record as properties on the containing class:
...
property RecField: Integer read FRec.A write FRec.A;
...
This will allow you to directly assign through the property to the field of that embedded record in the class instance.
Yes this is a problem. But the problem can be solved using record properties:
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;
This compiles and workes without problem.