Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Record schreibgeschützt weil Feld von Klasse (https://www.delphipraxis.net/171740-record-schreibgeschuetzt-weil-feld-von-klasse.html)

Jonas Shinaniganz 22. Nov 2012 14:08

Record schreibgeschützt weil Feld von Klasse
 
Zitat:

In Delphi 2010 und höher wird der Fehler E2064 auch vom Compiler ausgegeben, wenn Sie versuchen, einen Wert an einen Member eines Records zuzuweisen, der von einer schreibgeschützten Eigenschaft bereitgestellt wird. Betrachten Sie den folgenden Record-Typ:

TCustomer = record Age: Integer; Name: String; end;
Dieser Record wird von einer schreibgeschützten Eigenschaft in der folgenden Klasse bereitgestellt:

TExposing = class ... CurrentCustomer: TCustomer read SomeInternalField; ... end;
Die Zuweisung eines Wertes an die Eigenschaft CurrentCustomer oder an einen Member des von der Eigenschaft CurrentCustomer bereitgestellten Records führt zur Ausgabe des Fehlers E2064 durch den Compiler.
Von „http://docwiki.embarcadero.com/RADSt...Delphi)“
Kategorie: RAD Studio – Referenz

Was kann ich machen?

Muss doch möglich sein, einen Wert von außen zuzuweisen?

Delphi-Quellcode:
Tmyrecord = record
  a : integer;
  b : integer;
end;

myclass = class
private
  Fmyrecord : Tmyrecord;
public
  property myrecord : Tmyrecord read Fmyrecord write Fmyrecord ;
end;

Wirklich nur mit Pointern???... Wenn ja wie ist die Konvention?

himitsu 22. Nov 2012 14:15

AW: Record schreibgeschützt weil Feld von Klasse
 
Nein, Delphi hat endlich ordnungsgemäß diese Fehlermeldung. (war früher leider anders)

Du kannst nur den "kompletten" Record deinem Property zuweisen.


Wenn nicht, dann würde (eventuell über einen Getter) der Record ausgelesen, dadurch eine Kopie des Records angelegt und dann nur in der Kopie das Feld geändert.
(danach wird nämlich der Record nicht wieder an den "Setter" übergeben und zurückgeschrieben.

Du brauchst also eine Klasse (entweder statt des Records, oder als Wrapper dahin) oder du schreibst eben den ganzen Record zurück.

Delphi-Quellcode:
temp := o.myrecord;
temp.a := 666;
o.myrecord := temp;

Uwe Raabe 22. Nov 2012 14:23

AW: Record schreibgeschützt weil Feld von Klasse
 
... oder du gibst die Record-Member (zumindest die häufig genutzten) als eigene Properties an:

Delphi-Quellcode:
Tmyrecord = record
  a : integer;
  b : integer;
end;

myclass = class
private
  Fmyrecord : Tmyrecord;
public
  property myrecord : Tmyrecord read Fmyrecord write Fmyrecord ;
  property myrecordA : Integer read Fmyrecord.a write Fmyrecord.a;
  property myrecordB : Integer read Fmyrecord.b write Fmyrecord.b;
end;

Jonas Shinaniganz 22. Nov 2012 14:31

AW: Record schreibgeschützt weil Feld von Klasse
 
Okay alles klar, glücklicherweise passt es in meinem Fall ganz gut, einfach einen ganzen Record zu übergeben. Das muss ja früher schlimm gewesen sein. =) danke

himitsu 22. Nov 2012 14:50

AW: Record schreibgeschützt weil Feld von Klasse
 
Früher war es nicht schlimm.

Delphi-Quellcode:
o.myrecord.a := 666;
ließ sich problemlos compilieren.
(nur der zugwiesene Wert kam halt irgendwie nie an :angle2: )

Blup 23. Nov 2012 16:04

AW: Record schreibgeschützt weil Feld von Klasse
 
Da gibt es immer noch die bösen Pointer...
Delphi-Quellcode:
PMyRecord = ^TMyRecord
TMyRecord = record
  a : integer;
  b : integer;
end;

TMyClass = class(TObject)
private
  FMyRecord : TMyRecord;
  function GetMyRecord: PMyRecord;
public
  property MyRecord : PMyRecord read GetMyRecord;
end;

function TMyClass.GetMyRecord: PMyRecord;
begin
  Result := @FMyRecord;
end;

MyClass.MyRecord.a := 1;
MyClass.MyRecord.b := 2;

Jens01 23. Nov 2012 16:29

AW: Record schreibgeschützt weil Feld von Klasse
 
@Blup
Schöne Lösung, nur beim Auslesen fummel ich wieder mit dem Häkchen^ rum - oder hab ich was übersehen?
[Edit] ..okay, jetzt hab ich's verstanden... Glaub ich..

himitsu 23. Nov 2012 16:43

AW: Record schreibgeschützt weil Feld von Klasse
 
Wenn man auf ein Feld/Property/Methode des Record hinter dem Zeiger zugreift (
Delphi-Quellcode:
.igendwas
), dann dereferenziert Delphi das automatisch (implizit).

Elvis 23. Nov 2012 16:59

AW: Record schreibgeschützt weil Feld von Klasse
 
Records sind Werte, und IMO sollten Werte immutable sein.
Denn es gibt einfach (gerade in Delphi) zu viele, die überhaupt nicht wissen, was der eigene Code tatsächlich ausdrückt.
Records stellen gerne solche Fallen.
Und du bist da ganz offensichtlich reingetappt, als du versucht hast den Rückgabewert der Property zu ändern, in der Hoffnung den Wert, der hinter der Property steckt, zu ändern.

Wenn du dort etwas hast, was auch weitergereicht werden kann, dann sollte es eine Klasse sein.
Eigentlich sollten alle mutable Records Klassen oder Zeiger sein (Wobei Klassen eine schönere Syntax für Zeiger auf Records sind)

Da Records bei der Zuweisung kopiert werden, würden Änderungen nur in der einen Kopie wirksam sein:
Delphi-Quellcode:
var
  a, b :TRecord;
  list : TList<TRecord>;
begin
  b := list[2];
  b.X := 10;

  a := list[2];
  WriteLn(a.X);
end;
Records sind Werte, so wie ein Integer oder ein Double. Und Werte sollten immutable sein, oder man wird schizophren.
Wer Records nutzt weil er zu faul ist, den Speicher von Klassen zu verwalten, wird früher oder später über das oben erklärte Problem (Aliasing) stolpern.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:32 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz