AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Record Property verschachtelt - Schreibzugriff

Ein Thema von lxo · begonnen am 30. Mär 2021 · letzter Beitrag vom 30. Mär 2021
Antwort Antwort
lxo

Registriert seit: 30. Nov 2017
288 Beiträge
 
Delphi 12 Athens
 
#1

Record Property verschachtelt - Schreibzugriff

  Alt 30. Mär 2021, 09:19
Hallo,

mir ist vorhin aufgefallen, dass man bei verschachtelten Records keine Werte zuweisen kann.
Warum ist das so oder hab ich da irgendwie einen Denkfehler?

Delphi-Quellcode:
  TTestRec1 = record
  public
    IntValue: Integer;
  end;

  TTestRec2 = record // <- Wenn man das Record als Klasse deklariert funktioniert es
  public
    Test1: TTestRec1;
  end;

  TTestObj1 = class( TObject)
  private
    FTest2: TTestRec2;
  public
    property Test2 : TTestRec2 read FTest2 write FTest2;
  end;

...

procedure TForm53.FormCreate(Sender: TObject);
var
  ltest: TTestObj1;
begin
  ltest := TTestObj1.Create;
  ltest.Test2.Test1.IntValue := 10; // <- "Der linken Seite kann nichts zugewiesen werden"
  ltest.FTest2.Test1.IntValue := 10; // <- Funktioniert
end;
Mache ich aus TTestRec2 eine Klasse oder wenn ich statt auf die Property Test2 direkt auf FTest2 zugreife, funktioniert es.
Aber warum kann man da nichts eintragen wenn man die Property nutzt?
  Mit Zitat antworten Zitat
lxo

Registriert seit: 30. Nov 2017
288 Beiträge
 
Delphi 12 Athens
 
#2

AW: Record Property verschachtelt - Schreibzugriff

  Alt 30. Mär 2021, 09:41
Ich hab gerade bemerkt das es ja auch schon direkt bei der ersten Ebene nicht funktioniert.
Aber hab da noch eine andere Möglichkeit gefunden.

Delphi-Quellcode:
  TTestRec1 = record
  public
    IntValue: Integer;
  end;

  TTestObj1 = class( TObject)
  private
    FTest1: TTestRec1;
  public
    property Test1 : TTestRec1 read FTest1 write FTest1;
    property Test1IntValue : Integer read FTest1.IntValue write FTest1.IntValue; // <- So funktioniert es auch [1/2]
  end;

...

procedure TForm53.FormCreate(Sender: TObject);
var
  ltest: TTestObj1;
begin
  ltest := TTestObj1.Create;
  ltest.Test1.IntValue := 10; // <- "Der linken Seite kann nichts zugewiesen werden"
  ltest.Test1IntValue := 10; // <- So funktioniert es auch [2/2]
end;
Mir ist nur nicht ganz klar wieso das nicht funktioniert ein Record als Property zu verwenden und die einzelnen Eigenschaften des Records zuzuweisen.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.453 Beiträge
 
Delphi 12 Athens
 
#3

AW: Record Property verschachtelt - Schreibzugriff

  Alt 30. Mär 2021, 10:25
Wenn du ein Record als Property hast, dann greifst du beim Schreiben auf die Record-Felder ja auf den Getter des Properties zu. Dieser gibt dir aber eine Kopie des Records zurück und nicht das Record-Feld in der Klasse. Du änderst dann eben auch nie diese Kopie und nicht das Original.

Bedenke mal den Fall, wo der Getter eine Funktion ist, die den Record dynamisch zusammensetzt. Wo sollten dann deine Änderungen landen?
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von dummzeuch
dummzeuch

Registriert seit: 11. Aug 2012
Ort: Essen
1.604 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#4

AW: Record Property verschachtelt - Schreibzugriff

  Alt 30. Mär 2021, 10:44
Solange die Properties direkt auf die Felder zugreifen, hatte ich eigentlich gedacht, dass es funktioniert. Das mag allerdings bei verschiedenen Delphi-Versionen unterschiedlich sein.

ABER: Sobald Getter und Setter Methoden involviert sind, geht das spätestens zur Laufzeit schief, auch wenn es compiliert. Der Gettter liefert immer eine Kopie des Records zurück. Du änderst dann die Properties der Kopie und das Original bleibt unverändert.

Dasselbe gilt auch beim Aufruf von Methoden, die den Record verändern: Sie ändern die Kopie.

Edit: Uwe war schneller.
Thomas Mueller
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.068 Beiträge
 
Delphi 12 Athens
 
#5

AW: Record Property verschachtelt - Schreibzugriff

  Alt 30. Mär 2021, 11:26
Nein, es gibt immer eine Kopie und selbst wenn nicht, dann wäre es ein gefährlich/zufälliges Verhalten .. mit Getter oder nicht, mal Kopie oder nicht.

Man kann hier mit Klassen arbeiten
oder mit Properties im Record *1

1) im Record eine Referenz auf das Original und im Setter des Record-Property dann nicht nur im Record, sondern auch im Original ändern.




Toll wäre es, wenn Emba mal auf seine kunden hören und nicht zuviele Feature-/Bugreports sinnlos schließen würde.
Bei einem Schreibzugriff auf ein Property muß am Ende einfach nur nochmal der Setter aufgerufen werden.
Delphi-Quellcode:
X.MeinProperty.xxx := irgendwas

// wird ja als kompiliert
Temp := X.GetMeinProperty;
Temp.xxx := irgendwas
// und am Ende fehlt einfach nur noch eine implizite Zeile, nach dem Schreibzugriff
X.SetMeinProperty(Temp);
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.016 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#6

AW: Record Property verschachtelt - Schreibzugriff

  Alt 30. Mär 2021, 11:32
Geht auch mehrfach verschachtelt:
Delphi-Quellcode:
  TTestObj1 = class( TObject)
  private
    FTest2: TTestRec2;
  public
    property IntValue: Integer read FTest2.Test1.IntValue write FTest2.Test1.IntValue;
  end;

...

var
  ltest: TTestObj1;
begin
  ltest := TTestObj1.Create;
  ltest.IntValue := 10;
end;


Zum Problem an sich haben die anderen ja schon was gesagt - der Kern ist hier die API - die definiert hier eine Eigenschaft eines Wertetypens, und auch wenn der Zugriff auf ein Feld ohne Getter durch den Compiler letztlich im Binärcode als direkter Speicherzugriff implementiert wird und es auch einige Schlupflöcher(*) gibt, wird hier sichergestellt, dass man durch das direkte Zuweisen des Feldes auf das, was eine Kopie sein könnte nicht passiert.

(*)
1. Durch das Hinzufügen von Methoden zu Recordtypen wurde das ganze ein bisschen kompliziert gemacht - Beispiel:

Delphi-Quellcode:
type
  TTestRec = record
  public
    IntValue: Integer;
    procedure SetValue(i: Integer);
  end;

  TTestObj = class
  private
    FTest: TTestRec;
    function GetTest2: TTestRec;
  public
    property Test: TTestRec read FTest;
    property Test2: TTestRec read GetTest2;
  end;

procedure TTestRec.SetValue(i: Integer);
begin
  IntValue := i;
end;

function TTestObj.GetTest2: TTestRec;
begin
  Result := FTest;
end;

procedure Test;
var
  t: TTestObj;
begin
  t := TTestObj.Create;
  t.Test.SetValue(10);
  t.Test2.SetValue(20);
  Writeln(t.Test.IntValue); // was kommt raus? Spoiler: 10
end;
2. Wenn Eigenschaften direkt auf ein Feld gehen, kann man mit @ auf die Addresse "durchgreifen":

Delphi-Quellcode:
procedure SetValue(val: PInteger; i: Integer);
begin
  val^ := i;
end;

...

procedure Test;
var
  t: TTestObj;
begin
  t := TTestObj.Create;
  SetValue(@t.Test.IntValue, 30); // funktioniert
  SetValue(@t.Test2.IntValue, 40); // funktioniert nicht - compilefehler E2036 Variable required
end;
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (30. Mär 2021 um 11:48 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von joachimd
joachimd

Registriert seit: 17. Feb 2005
Ort: Weitingen
679 Beiträge
 
Delphi 12 Athens
 
#7

AW: Record Property verschachtelt - Schreibzugriff

  Alt 30. Mär 2021, 11:57
und als Ergänzung, wenn Du mit Klassen statt Records arbeitest: Verwende Interfaces, damit Du Dich nicht mehr um das Release kümmern musst (zB beim Zuweisen eines neuen Objekts an das Property).
Joachim Dürr
Joachim Dürr Softwareengineering
http://www.jd-engineering.de
  Mit Zitat antworten Zitat
lxo

Registriert seit: 30. Nov 2017
288 Beiträge
 
Delphi 12 Athens
 
#8

AW: Record Property verschachtelt - Schreibzugriff

  Alt 30. Mär 2021, 14:29
Vielen Dank für die ausführlichen Erklärungen.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:51 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