Das Problem ist das der Access auf den Member nicht den Setter aufruft sondern den Getter, du Holst dir also eine Temporäre Kopie des Records durch den Getter und Greifst auf dessen X zu. Selbst wenn der Compiler das nicht abfangen würde, würde es nicht den Korrekten Record ändern, sondern nur die Temporäre Kopie die du aus dem Getter bekommst.
Die einfachste lösung ist ne simple update funktion:
Code: Alles auswählen
function UpdateX(const InpRec: TMyRec; NewX: Integer): TMyRec;
begin
Result := InpRec;
Result.X := NewX;
end;
MyClass.Records[i] := UpdateX(MyClass.Records[i], 42);
Mit advanced Records geht das auch als Methode oder als Operator:
Code: Alles auswählen
Type TMyRecord = record
X: Integer;
function UpdateX(NewX: Integer);
end;
function TMyRecord.UpdateX(NewX: Integer): TMyRec;
begin
Result := Self;
Result.X := NewX;
end;
MyClass.Records[i] := MyClass.Records[i].UpdateX(42);
Das ist grundsätzlich die sauberste Lösung weil du nicht im Speicher der von einem Anderen Objekt Gemanaged wirst rumhantierst. Man hat hier eine All or Nothing Eigenschaft, das man nur Records als ganze Updaten kann (und somit z.B. Plausibilitätschecks zu jedem Zeitpunkt durchführen kann). Macht auch Synchronisation für multithreaded Anwendungen massiv viel einfacher
Alternativ wenn du inplace arbeiten willst kannst du auch einfach dir einen Pointer auf den Record rausgeben lassen:
Code: Alles auswählen
PMyRec = ^TMyRec;
TMyClass = class
...
property ItemPtr[AIndex: Integer]: PMyRec read GetItemPtr;
end;
MyInstance.ItemPtr[i]^.X := 42;
Hier musst du aber sicher sein das der Pointer Zugriff alles richtig macht, weil du keinen Setter und Damit keine Plausibilitätschecks zwischenschalten kannst. Außerdem würden potentielle Events die der Setter Triggert nicht ausgeführt und müssten Manuell Nachgecalled werden. Von daher ist das die Unsauberere Lösung, ist aber deutlich Effizienter (Laufzeit und Speicher, da keine Zwischenkopien erstellt werden).
Daher würde ich meist empfehlen eine Updater Funktion zu schreiben, und nur wenn du Performance Probleme hast auf die Inplace Variante wechseln