AGB  ·  Datenschutz  ·  Impressum  







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

Kopieren des Inhalt eines Record

Ein Thema von DelphiFan2008 · begonnen am 18. Okt 2013 · letzter Beitrag vom 20. Okt 2013
Antwort Antwort
Seite 1 von 2  1 2      
DelphiFan2008

Registriert seit: 4. Dez 2008
81 Beiträge
 
Delphi XE2 Starter
 
#1

Kopieren des Inhalt eines Record

  Alt 18. Okt 2013, 21:21
Hallo Forum,

gibt es eine einfachere Möglichkeit?

Ich arbeite häufig mit TList Objekten in denen ich Records verwalte. Beispiel
Delphi-Quellcode:
type PTest = ^TTest
     TTest = record
       s1 : String;
       d1 : Double;
       i1 : Integer;
       s2 : String;
       l1 : LongInt;
       s3 : String;
       n1 : Int64;
     end;
dieser wird in der Liste über .Add( P ); // P : PTest hinzugefügt.

Wenn ich nun den Inhalt eines Records in einen neuen kopieren möchte erfolgt dies in ähnlicher Forem wie..

Delphi-Quellcode:
function MyList.CopyToNewItem( Index:Integer;APTest:PTest );
var FPTest : PTest;
begin
  FPTest := PTest( Self.Items[Index] )

  ATest^.s1 := FPTest^.s1;
  ATest^.d1 := FPTest^.d1;
  ATest^.i1 := FPTest^.i1;
  ATest^.s2 := FPTest^.s2;
  usw.
end;
Falls im Record eine Variable hinzugefügt wird muss dies immer in der Kopierroutine nachgezogen werden. Gibt es eine einfachere Möglichkeit den Inhalt eines Record in einen anderen zu kopieren als jede einzelne Variable oder Struktur einzeln?

Gruss DelphiFan2008
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.159 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: Kopieren des Inhalt eines Record

  Alt 18. Okt 2013, 21:36
Direktes Kopieren des Speicherauszugs (Copy, CopyMemory oder sowas) geht natürlich, fällt aber schon in deinem Fall von TTest flach: Das würde die Referenzzählung des Strings zerstören - Tödlich.

Ich habe auch nie etwas besseres gefunden. Die einzige Möglichkeit ist irgendwie halt dem Record einen Konstruktor bzw. Funktion zu bauen die als Parameter einen bereits bestehenden Record nimmt und die Daten in den neuen überträgt...
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.582 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Kopieren des Inhalt eines Record

  Alt 18. Okt 2013, 21:53
Ich frage mich immer wieder warum man sich das Leben mit Records so schwer machen kann. Eine TObjectList<TTest> ist doch sehr viel einfacher und bequemer als die ganze Pointer- und Speicherspielerei...

Aber wie dem auch sei... zur Frage:
Delphi-Quellcode:
procedure TMyList.CopyToNewItem(Index: Integer; APTest: PTest);
begin
  APTest^ := Self.Items[Index]^;
end;
// EDIT:
Beispiel:
Delphi-Quellcode:
type
  PTest = ^TTest;

  TTest = record
    s1: String;
    d1: Double;
    i1: Integer;
    s2: String;
    l1: LongInt;
    s3: String;
    n1: Int64;
  end;

  TMyList = class(TList<PTest>)
  public
    procedure CopyToNewItem(Index: Integer; APTest: PTest);
  end;

procedure TMyList.CopyToNewItem(Index: Integer; APTest: PTest);
begin
  APTest^ := Self.Items[Index]^;
end;

// Test
var
  Test: TMyList;
  Current: PTest;
begin
  Test := TMyList.Create;
  try
    New(Current);
    Current.s1 := 'Test 1';
    Test.Add(Current);
    New(Current);
    Current.s1 := 'Test 2';
    Test.Add(Current);
    New(Current);
    Current.s1 := 'Nothing';
    Test.CopyToNewItem(0, Current);
    ShowMessage(Current.s1); // ergibt Test 1
  finally
    Test.Free;
  end;
end;
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#4

AW: Kopieren des Inhalt eines Record

  Alt 18. Okt 2013, 21:57
Wäre eine TList<TTest> mit TTest als record in dem Fall nicht sogar noch einfacher? (Disclaimer: Habe kein Delphi mit Generics-Support)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.582 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Kopieren des Inhalt eines Record

  Alt 18. Okt 2013, 22:01
Wäre eine TList<TTest> mit TTest als record in dem Fall nicht sogar noch einfacher? (Disclaimer: Habe kein Delphi mit Generics-Support)
Theoretisch ja, aber dann kann man den Record in der Liste nur durch Neuzuweisung bearbeiten, nicht ein einzelnes Feld.

Deshalb wären ja Klassen auch viel sinnvoller. Nur das Kopieren ist bei Klassen nicht so einfach durch Zuweisung möglich.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#6

AW: Kopieren des Inhalt eines Record

  Alt 18. Okt 2013, 22:27
Ich frage mich immer wieder warum man sich das Leben mit Records so schwer machen kann. Eine TObjectList<TTest> ist doch sehr viel einfacher und bequemer als die ganze Pointer- und Speicherspielerei...
...
Delphi-Quellcode:
  
APTest^ := Self.Items[Index]^;
Du hast natürlich im Prinzip Recht, nur hier (Inhalte kopieren) ausnahmsweise nicht. Dessenungeachtet sind die Unterschiede bezüglich der Pointer- und Speicherspielerei zwischen Record und Klasse nicht sonderlich groß bzw. eigentlich kaum vorhanden. Hier 'New', da 'Create', hier 'Dispose', da 'Free'. Und das '^' kann man ja mittlerweile auch weglassen.

Bei der TObjectList wird die Sache natürlich anders (aufräumen und so).

Aber reden wir nicht weiter davon. Klassen sind einfach besser weil mächtiger,dafür sind Records einfacher und bla bla bla.
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.582 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Kopieren des Inhalt eines Record

  Alt 18. Okt 2013, 22:38
Du hast natürlich im Prinzip Recht, nur hier (Inhalte kopieren) ausnahmsweise nicht.
Habe ich ja auch geschrieben. Aber die paar Zeilen für die Implementierung von Assign sollten nicht stören.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
DelphiFan2008

Registriert seit: 4. Dez 2008
81 Beiträge
 
Delphi XE2 Starter
 
#8

AW: Kopieren des Inhalt eines Record

  Alt 20. Okt 2013, 08:17
@jaenicke,

danke für die Antworten. Frage: Wie würde denn ein alternativer Ansatz mit TObjectList<TTest> in diesem Fall aussehen. Mir fehlt die Erfahreung mit neueren Konstrukten. Arbeite noch immer vorwiegend mit Record, Pointer und den Basisklassen welche schon ab etwa Delphi3 bekannt sind und welchen Vorteil hätte ich?

Gruß DelphiFan2008
  Mit Zitat antworten Zitat
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#9

AW: Kopieren des Inhalt eines Record

  Alt 20. Okt 2013, 09:59
ObjectLists sind (im Gegensatz zu Records) vergleichsweise problemlos und einfach zu handhaben. Ich hab noch Delphi2007, deshlab muß ich die property Items überschreiben (brauchst du bei <TTest> nicht).

Delphi-Quellcode:
uses
  .. Contnrs;

type
  TTest = class
  private
    FD1: Double;
    FN1: Int64;
    FI1: Integer;
    FL1: LongInt;
    FS1: String;
    FS2: String;
    FS3: String;
  public
    property D1: Double read FD1 write FD1;
    property N1: Int64 read FN1 write FN1;
    property I1: Integer read FI1 write FI1;
    property L1: LongInt read FL1 write FL1;
    property S1: String read FS1 write FS1;
    property S2: String read FS2 write FS2;
    property S3: String read FS3 write FS3;
    procedure Clear;
    procedure Assign(Value: TTest);
  end;

  TTestList = class(TObjectList)
  private
    function GetItems(Index: integer): TTest;
  public
    property Items[Index: integer]: TTest read GetItems; default;
  end;

..

{ TTest }

procedure TTest.Assign(Value: TTest);
begin

end;

procedure TTest.Clear;
begin

end;

{ TTestList }

function TTestList.GetItems(Index: integer): TTest;
begin
  Result := TTest(inherited Items[Index]);
end;

..

var
  TestList: TTestList;
  Index: integer;
begin
  TestList := TTestList.Create;
  try
    // Hinzufügen von Items;
    Index := TestList.Add(TTest.Create);
    TestList[Index].Clear; // Das z.B. ginge bei einem Record nicht
    TestList[Index].S1 := 'Hello TObjectList';
    // Löschen von Items;
    TestList.Delete(Index);
  finally
    TestList.Free;
  end;
end;

Geändert von Bjoerk (20. Okt 2013 um 10:01 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.582 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Kopieren des Inhalt eines Record

  Alt 20. Okt 2013, 10:18
@Bjoerk:
Ohne Generics macht das ganze nicht so viel Sinn.
Und Clear kannst du auch problemlos in einen Record einbauen...


Ein komplettes Beispiel mit einigen der Möglichkeiten findest du hier.

Ein Vorteil ist, dass du dich nicht selbst um die Pointer kümmern musst. Du hast einfach immer eine Referenz, also einen impliziten Pointer, und fertig. Für das Zuweisen der Werte kannst du, wenn du von TPersistent ableitest, Assign oder AssignTo überschreiben (oder du implementierst es als normale Methode neu, wenn du von TObject ableitest).
Vorteil des Überschreibens von AssignTo:
Es wird schon vorher geprüft, ob nil übergeben wurde und ggf. ein qualifizierter Fehler ausgelöst und wenn die falsche Klasse zugewiesen wird, brauchst du nur inherited aufrufen und es kommt auch ein qualifizierter Fehler.

Du musst keine Properties verwenden, du kannst es also auch genauso schreiben wie du es bei Records hattest (die heute aber auch Properties kennen), aber die haben den Vorteil, dass die privaten Felder nicht direkt erreichbar sind und du ggf. leicht Setter oder Getter einbauen kannst.

Ein wenig mehr Quelltext ist es in der Klasse oft schon, aber dafür ist die Verwendung sehr viel einfacher. In der Praxis wird die Anzahl der Verwendungen sehr viel höher sein als die einmalige Implementierung der Klasse, so dass es sehr viel sinnvoller ist die Verwendung zu vereinfachen als bei der Implementierung der Klasse selbst zu sparen.
Delphi-Quellcode:
unit Unit15;

interface

uses
  System.Generics.Collections, System.Classes, Vcl.Dialogs;

procedure Test;

implementation

type
  TTest = class(TPersistent)
  private
    var
      FString1: String;
      FString2: String;
      FDouble1: Double;
  protected
    procedure AssignTo(Dest: TPersistent); override;
  public
    constructor Create(const AString1: string; const AString2: string = ''; const ADouble1: Double = 0.0); overload;
    constructor Create(const ACloneSource: TTest); overload;
    property String1: String read FString1 write FString1;
    property Double1: Double read FDouble1 write FDouble1;
    property String2: String read FString2 write FString2;
  end;

  TMyList = class(TObjectList<TTest>)
  public
  end;

procedure Test;
var
  Test: TMyList;
  Current: TTest;
begin
  Test := TMyList.Create(True);
  try
    Test.Add(TTest.Create('Test 1'));
    Test.Add(TTest.Create('Test 2'));
    Test.Add(TTest.Create('Hallo'));
    Current := TTest.Create('Clone Source');
    try
      Test.Add(TTest.Create(Current)); // Neues Objekt aus Current erzeugen
    finally
      Current.Free;
    end;

    for Current in Test do
      ShowMessage(Current.String1); // alle ausgeben

    // zuweisen
    Current := TTest.Create;
    try
      Current.Assign(Test[2]);
      ShowMessage(Current.String1); // Hallo
    finally
      Current.Free;
    end;
  finally
    Test.Free; // Die Objekte in der Liste werden durch das True für OwnsObjects im Konstruktor freigegeben
  end;
end;

{ TTest }

procedure TTest.AssignTo(Dest: TPersistent);
var
  Destination: TTest;
begin
  if Dest is TTest then
  begin
    Destination := TTest(Dest);
    Destination.String1 := FString1;
    Destination.String2 := FString2;
    Destination.Double1 := FDouble1;
  end
  else
    inherited;
end;

constructor TTest.Create(const AString1: string; const AString2: string = ''; const ADouble1: Double = 0.0);
begin
  FString1 := AString1;
  FString2 := AString2;
  FDouble1 := ADouble1;
end;

constructor TTest.Create(const ACloneSource: TTest);
begin
  Assign(ACloneSource);
end;

end.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 22:25 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