Reputation: 13345
Is their any drawback to declare a property of type record ?
TMyObject = class(TObject)
private
FSomeRecord: TMyRecord;
public
property SomeRecord: TMyRecord read FSomeRecord write FSomeRecord;
end;
How the instruction Myobject.SomeRecord.xxx := yyy
will work under the hood (I think this can not work actually) ?
If it's can not work, how to do with record property? is it simply better to avoid it and declare TMyobject like below?
TMyObject = class(TObject)
public
SomeRecord: TMyRecord;
end;
Upvotes: 1
Views: 476
Reputation: 8243
One way to circumvent this is to declare the property as a POINTER to the record (if you only need access to the fields/methods within the record):
TYPE
TMyRecord = RECORD
Field1 : INTEGER;
END;
PMyRecord = ^TMyRecord;
TYPE
TMyClass = CLASS
PRIVATE
FMyRecord : TMyRecord;
FUNCTION GetRec : PMyRecord;
PUBLIC
PROPERTY MyRec : PMyRecord Read GetRec;
END;
{ TMyClass }
FUNCTION TMyClass.GetRec : PMyRecord;
BEGIN
Result:=@FMyRecord
END;
.
.
.
VAR
MC : TMyClass;
.
.
.
MC.MyRec.Field1:=12
.
.
.
Due to the "Extended syntax", you can short-circuit the normal syntax of
MC.MyRec^.Field1:=12
to
MC.MyRec.Field1:=12
but not the following use:
VAR NewRec : TMyRecord := MC.MyRec;
which would have to be coded as
VAR NewRec : TMyRecord := MC.MyRec^;
unless you introduce a RECORD HELPER for the PMyRecord that implements an implicit cast to TMyRecord:
TYPE
PMyRecHelper = RECORD HELPER FOR PMyRecord
CLASS OPERATOR Implicit(P : PMyRecord) : TMyRecord;
END;
{ PMyRecHelper }
CLASS OPERATOR PMyRecHelper.Implicit(P : PMyRecord) : TMyRecord;
BEGIN
Result:=P^
END;
Unfortunately, the above code, while it compiles, doesn't work. Delphi does not allow operator overloaders in record helpers...
So until this last item is implemented, you only have a semi-working implementation...
Upvotes: 1
Reputation: 595392
You are correct that Myobject.SomeRecord.xxx := yyy
will not work the way you want. It will invoke the property getter, returning a copy of the record, and then you would be updating the xxx
field of the copy, not the original. Essentially, the generated code would act like this:
var tmp: TMyRecord;
tmp = Myobject.FSomeRecord;
tmp.xxx := yyy;
Unless you need RTTI for the property, there is no good reason to declare a read+write property that simply accesses a field directly. Just expose public access to the field instead.
Upvotes: 2