Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Eine Liste von Objekten speichern (https://www.delphipraxis.net/80745-eine-liste-von-objekten-speichern.html)

Luckie 14. Nov 2006 16:35


Eine Liste von Objekten speichern
 
Ich versuche gerade verzweifelt eine Liste von Objekten zu speichern:
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    btnKundeNeu: TButton;
    procedure btnKundeNeuClick(Sender: TObject);
  private
    { Private declarations }
    FKundenListe: array of TBankKunde;
    procedure UpdateListbox;
  public
    { Public declarations }
  end;

var
  Form1             : TForm1;

const
  FRMCAPTION       = 'Meine kleine Bank - %s';

implementation

{$R *.dfm}

procedure TForm1.UpdateListbox;
var
  i                : Integer;
  KundenName       : string;
  BankKunde        : TBankKunde;
begin
  Listbox1.Clear;
  for i := 0 to length(FKundenListe) - 1 do
  begin
    BankKunde := TBankKunde.Create;
    try
      BankKunde := FKundenListe[i];
      KundenName := BankKunde.Name;
    finally
      BankKunde.Free;
    end;
    ListBox1.Items.Add(KundenName);
  end;
end;

procedure TForm1.btnKundeNeuClick(Sender: TObject);
var
  BankKunde        : TBankKunde;
  KundenName       : string;
  len: Integer;
begin
  KundenName := InputBox('Neuer Kunden', 'Name des Kunden:', '');
  BankKunde := TBankKunde.Create;
  try
    try
      BankKunde.Name := KundenName;

      len := length(FKundenListe);
      SetLength(FKundenListe, len + 1);
      FKundenListe[len] := BankKunde;
    except
      on E: Exception do
        MessageBox(Handle, PChar(E.Message), PChar('Neuen Kunde anlegen'), MB_ICONSTOP);
    end;
  finally
    BankKunde.Free;
  end;
  UpdateListbox;
end;
Aber die Listbox bleibt leer. Nehme ich das BankKunde.Free in Zeile 64 weg, geht es genau einmal. Will ich ein zweites Objekt hinzufügen bekomme ich eine AccessViolation.

Ich habe auch schon versucht mit einer TList zu arbeiten, aber das hat auch nicht geklappt. Es muss doch eine Möglichkeit geben ein Objekt zu speichern und nicht nur einen Zeiger auf das Objekt, der wieder ungültig wird, wenn das Objekt freigegeben wird. Oder muss ich mir extra eine Klasse TKundenListe schreiben, die dann die Objekte vom Typ TBankKunde aufnimmt?

Christian Seehase 14. Nov 2006 16:43

Re: Eine Liste von Objekten speichern
 
Moin Luckie,

wenn die FKundenliste schon die Objekte vom Typ TBankkunde enthält, müsste

Delphi-Quellcode:
    BankKunde := TBankKunde.Create; // Hier erzeugst Du eine Instanz von TBankkunde
    try
      BankKunde := FKundenListe[i]; // und hier überschreibst Du den Pointer auf das Objekt wieder
      KundenName := BankKunde.Name;
    finally
      BankKunde.Free;              // Hier wird das Objekt freigegeben, auf das FKundenListe[i] verweist.
    end;

so aussehen:

Delphi-Quellcode:
    BankKunde := FKundenListe[i];
    KundenName := BankKunde.Name;

    // oder gleich so

    KundenName := FKundenListe[i].Name;
[EDIT]
Analog gilt das dann natürlich auch für die das Hinzufügen von Werten zu der Liste.
Du musst das Objekt erzeugen, aber nicht gleich wieder freigeben (Zeile 64).
Die Freigabe erfolgt dann irgenwann später, wenn Du den Listeninhalt nicht mehr benötigst.
[/EDIT]

DGL-luke 14. Nov 2006 16:56

Re: Eine Liste von Objekten speichern
 
Hallo Luckie,

(verzeih mir, wenn du das alles schon weißt) ein objekt ist erst einmal nur ein zeiger auf einen speicherbereich. geht dir der zeiger verloren, hast du pech gehabt, du kommst wohl nicht mehr ans objekt ran. Wenn du das Objekt also "speichern" willst, wäre eine Möglichkeit, dir zwei Routinen zu schreiben, die das Objekt in einen Stream schreiben bzw. aus ihm lesen. Die RTTI kann das übrigens auch, da musst du nur mal nach Hier im Forum suchenserialisieren suchen.

Ansonsten solltest du verhindern,

a) den Zeiger auf ein Objekt zu verlieren (man kann ihn in einer TList oder besser TObjectlist ablegen, das ganze kann man auch noch typisieren, siehe typisierte Listetypisierte Liste)
b) das Objekt freizugeben, bevor du sicher bist, dass du es nicht mehr brauchst.

Und wo genau hast du jetzt Probleme?

ach ja...

Delphi-Quellcode:
BankKunde := FKundenListe[i];
:gruebel: was willst du da tun? du erstellst einen neuen bankkunden (über TBankkkunde.Create). in Bankkunde liegt dann der zeiger auf dieses objekt. Und jetzt weist du ein element eines mit 0 initalisierten arrays darauf zu... das kann nicht gut enden :zwinker:

Luckie 14. Nov 2006 17:02

Re: Eine Liste von Objekten speichern
 
Ah ja gut. Ich habe mich abr entschieden es anders zu machen und zwar mit einer extra Klasse:
Delphi-Quellcode:
type
  TBankKunde = class(TObject)
  private
    FName: String;
    procedure SetName(Name: String);
    function GetName: String;
  public
    property Name: String read GetName write SetName;
  end;

  TBankKundeCollection = class(TList)
  private
    function Get(Index: Integer): TBankKunde;
  public
    procedure Add(Item: TBankKunde);
    property Items[Index: Integer]: TBankKunde read Get;
  end;
Die Klasse TBankKundeCollection soll mir eine Liste der BankKunden verwalten. Aber da habe ich ein Problem mit:
Delphi-Quellcode:
procedure TForm1.UpdateListbox;
var
  i                : Integer;
  KundenName       : string;
  BankKunde        : TBankKunde;
begin
  Listbox1.Clear;
  for i := 0 to FKundenListe.Count - 1 do
  begin
    BankKunde := FKundenListe.Items[i];
    KundenName := BankKunde.Name;
    ListBox1.Items.Add(KundenName);
  end;
  ShowMessage(IntToStr(FKundenListe.Count));
end;

procedure TForm1.btnKundeNeuClick(Sender: TObject);
var
  BankKunde        : TBankKunde;
  KundenName       : string;
begin
  KundenName := InputBox('Neuer Kunden', 'Name des Kunden:', '');
  BankKunde := TBankKunde.Create;
  try
    try
      BankKunde.Name := KundenName;
      FKundenListe.Add(BankKunde);
    except
      on E: Exception do
        MessageBox(Handle, PChar(E.Message), PChar('Neuen Kunde anlegen'), MB_ICONSTOP);
    end;
  finally
    //BankKunde.Free;
  end;
  UpdateListbox;
end;
In Zeile 33 kann ich das Objekt ja nicht frei geben. Wie gebe ich das am besten frei? Oder wird das automatisch freigegeben, wenn ich die BankKundenCollection (FKundenListe) zerstöre?

Christian Seehase 14. Nov 2006 17:09

Re: Eine Liste von Objekten speichern
 
Moin Luckie,

für die Freigabe sollte das Listenobjekt zuständig sein.
Im Destruktor wird die Liste durchgegangen und alle enthaltenen Objekte freigegeben.

Ersatzweise könntest Du auch eine TObjectList nehmen, und hierbie OwnsObjects auf true setzen.

Luckie 14. Nov 2006 17:12

Re: Eine Liste von Objekten speichern
 
So habe ich es jetzt auch gelöst:
Delphi-Quellcode:
procedure TBankKundeCollection.Free;
var
  i                : Integer;
begin
  for i := 0 to self.Count - 1 do
    self.Items[i].Free;
end;
Eine TObjectList kennt mein Delphi 6 Personal nicht.

NormanNG 14. Nov 2006 17:13

Re: Eine Liste von Objekten speichern
 
Hi,

du darfst das Object dort garnicht freigeben. Du hast den Zeiger auf das Objekt in deiner Collection und zusätzlich in Bankkunde. Wenn die nun Bankkunde freigibst, ist der Zeiger ( auf das nun ungültige Objekt) in deiner Collection noch drin. Den kannst du aber nicht mehr verwenden.

Also: Bankkunde beim Neuanlegen nicht freigeben, sondern irgendwann (mit dem Zerstören der Collection).

[edit] roter kasten, aber trotzdem... [/edit]

shmia 14. Nov 2006 17:24

Re: Eine Liste von Objekten speichern
 
Zitat:

Zitat von Luckie
Eine TObjectList kennt mein Delphi 6 Personal nicht.

Delphi-Quellcode:
Uses ...,Contnrs;
Also ich bin überzeugter TObjectList Benutzer, weil es die Arbeit sehr erleichtert.

Luckie 14. Nov 2006 17:28

Re: Eine Liste von Objekten speichern
 
Die Unit kenne ich noch gar nicht. :shock:

Ok, habe es jetzt so gelöst. ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:44 Uhr.

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