I\'m curious to know why Delphi treats record type properties as read only:
TRec = record
A : integer;
B : string;
end;
TForm1 = class(TForm)
Like others have said - the read property will return a copy of the record, so the assignment of fields isn't acting on the copy owned by TForm1.
Another option is something like:
TRec = record
A : integer;
B : string;
end;
PRec = ^TRec;
TForm1 = class(TForm)
private
FRec : PRec;
public
constructor Create;
destructor Destroy; override;
procedure DoSomething(ARec: TRec);
property Rec : PRec read FRec;
end;
constructor TForm1.Create;
begin
inherited;
FRec := AllocMem(sizeof(TRec));
end;
destructor TForm1.Destroy;
begin
FreeMem(FRec);
inherited;
end;
Delphi will dereference the PRec pointer for you, so things like this will still work:
Form1.Rec.A := 1234;
There's no need for a write part of the property, unless you want to swap the PRec buffer that FRec points at. I really wouldn't suggest to do such swapping via a property anyway.
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.