![]() |
Kopie eines Item aus der TObjectList
Hallo Zusammen,
die Frage vorab: Wenn ich aus einer TObjectList ein item hole etwa so:
Delphi-Quellcode:
bekomme ich dan den Pointer des items oder das item selbst?
CarPosColl := RawTagesauswertung.Items[i];
Ich hätte gerne eine kopie des items. Ich habe eine Klasse von TObject die Autos verwaltet. Dann eine Klasse TCarPosCollection von TObjectList die x Autos verwaltet. Und zuletzt eine Klasse Tagesauswertung ebenfals aus TObjectList welche x TCarPosCollection verwaltet. In einer Schleife lese ich aus der TObjectList "Tagesauswertung" ein paar items und übergebe diese zum verarbeiten in einer zweiten instanz von Klasse. So wird die übergabe der items gemacht:
Delphi-Quellcode:
Wenn ich die Schleife nur ein mal ausführe, funkt alles einwandfrei.
CarPosColl := RawTagesauswertung.Items[i];
Wenn ich die Schleife ein zweites mal durchführe und dabei vorher CarPosColl.free aufrufe, bekomme ich eine exception "EAccessViolation". Ich vermute das ich keine kopie übergebe sonder nur den Pointer des items welches in meiner Hauptliste steckt. Der Destructor versucht vermutlich das item aus der Haptliste zu bereinigen. Habs auch so probiert und bekomme beim free die exception "EPrivilege"
Delphi-Quellcode:
CarPosColl := TCarPosCollection.Create; CarPosColl := RawTagesauswertung.Items[i]; Hat jemand eine Idee? Hier meine Klassen aus das wesendliche reduziert: Gruß Kostas
Delphi-Quellcode:
type
TCarPos = class(TObject) private FZeitpunkt:TDateTime; FCarID:integer; Procedure SetZeitpunkt(value :TDateTime); function GetZeitpunkt:TDateTime; Procedure SetCarID(value :Integer); function GetCarID:Integer; public constructor Create; property Zeitpunkt: TDateTime read GetZeitpunkt write SetZeitpunkt; property CarID: Integer read GetCarID write SetCarID; end; TCarPosCollection =Class(TObjectList) private FZustand:Boolean; function Get(Index: Integer): TCarPos; procedure SetZustand(value :Boolean); function GetZustand:Boolean; public destructor Destroy; override; procedure Add(Item: TCarPos); property Items[Index: Integer]: TCarPos read Get; property Zustand:Boolean read GetZustand write SetZustand; end; TTagesauswertung =Class(TObjectList) private function Get(Index: Integer): TCarPosCollection; public destructor Destroy; override; procedure Add(Item: TCarPosCollection); property Items[Index: Integer]: TCarPosCollection read Get; end; destructor TCarPosCollection.Destroy; var i: Integer; begin for i := 0 to self.Count - 1 do self.Items[i].Free; inherited; end; procedure TCarPosCollection.Add(Item: TCarPos); begin inherited Add(Item); end; function TCarPosCollection.Get(index: integer):TCarPos; begin result := inherited Get(Index); end; destructor TTagesauswertung.Destroy; var i: Integer; begin for i := 0 to self.Count - 1 do self.Items[i].Free; inherited; end; procedure TTagesauswertung.Add(Item: TCarPosCollection); begin inherited Add(Item); end; function TTagesauswertung.Get(index: integer):TCarPosCollection; begin result := inherited Get(Index); end; |
Re: Kopie eines Item aus der TObjectList
Geb bei der 2. Liste einfach beim Constructor Aufruf ein False mit, dann gibt die TObjectList nicht die Items frei, die in ihr sind. Damit bleiben dann die in der Hauptliste auch weiterhin gültig.
Du bekommst einen Instanzenzeiger. Die TObjectListe verwaltet nur die Instanzenzeiger. |
Re: Kopie eines Item aus der TObjectList
Du überschreibst bei Deiner TCarPosCollection die Destroy-Methode der TObjectList und gibts alle Items frei. Das ist nicht nötig, das macht TObjectList schon.
Hier mal ein Grundgerüst für KLassen, die von TObjectList erben und somit ein Typecasting überflüssig machen: Ersetze Name durch Deine Klasse (TCarPos)
Delphi-Quellcode:
NameObjectList = class(TObjectList)
protected function GetItem(Index: Integer): Name; procedure SetItem(Index: Integer; AItem: Name); public function Add(AItem: Name): Integer; function Extract(Item: Name): Name; function Remove(AItem: Name): Integer; function IndexOf(AItem: Name): Integer; procedure Insert(Index: Integer; AItem: Name); function First: Name; function Last: Name; property Items[Index: Integer]: Name read GetItem write SetItem; default; end; implementation { NameObjectList } function NameObjectList.Add(AItem: Name): Integer; begin Result := inherited Add(AItem); end; function NameObjectList.Extract(Item: Name): Name; begin Result := Name(inherited Extract(Item)); end; function NameObjectList.First: Name; begin if Count = 0 then Result := nil else Result := Name(inherited First); end; function NameObjectList.GetItem(Index: Integer): Name; begin Result := Name(inherited Items[Index]); end; function NameObjectList.IndexOf(AItem: Name): Integer; begin Result := inherited IndexOf(AItem); end; procedure NameObjectList.Insert(Index: Integer; AItem: Name); begin inherited Insert(Index, AItem); end; function NameObjectList.Last: Name; begin if Count = 0 then Result := nil else Result := Name(inherited Last); end; procedure NameObjectList.SetItem(Index: Integer; AItem: Name); begin inherited Items[Index] := AItem; end; function NameObjectList.Remove(AItem: Name): Integer; begin Result := inherited Remove(AItem);end; |
Re: Kopie eines Item aus der TObjectList
Zitat:
|
Re: Kopie eines Item aus der TObjectList
Danke Muetze1 und sh17,
das ist interessant. Es wird also wirklich keine Kopie des items erzeugt. Ich benötige unbedingt eine Kopie der items, weil während dem Verarbeiten ich ein paar Eigenschaften der items verändere. Diese Änderung darf sich jedoch nicht im Master widerspiegeln. Ich habe leider noch nicht verstanden warum ich die ObjectList nicht leeren darf. Nochmals kurz beschrieben was ich eigentlich vor habe. Es gibt eine ObjectList Instanz "TTagesauswertung" die hält alle Daten vor die aus einem Select aus der DB befühlt wird. Die nenne ich jetzt mal Master. Jetzt möchte ich die Daten verarbeiten. Ich erzeuge eine weitere, leere Instanz von "TTagesauswertung". Die nenne ich mal Slave. Danach gehe ich alle items von Master durch und hole mir ein paar items zum verarbeiten in die Slave. Dieser Vorgang wird mehrmals wiederholt. Dabei sollen die Master unverändert bleiben. Wenn ich also fertig bin, rufe ich Slave.free und Slave := TTagesauswertung.Create; auf. Ihr meint jetzt, der constructor darf die items nicht freigeben. Sicherlich habt Ihr Recht. Ich verstehe es nur noch nicht warum. Die items von Master dürfen sicherlich nicht freigegeben werden, aber die items von Slave müssen doch freigegeben werden oder? Wie bereits erwähnt, wird Slave öfters erzeugt, befüllt und wieder zerstört. Habt Ihr eine Idee? |
Re: Kopie eines Item aus der TObjectList
TObjectList bietet einen Mechanismus zum Verwalten seiner Items. Ruft man TObjectList.Create(true) auf, gehören die Items dieser Objectlist und sie werden bei ObjectList.clear bzw ObjectList.Free von dieser wieder freigegeben.
Ruft man TObjectList.Create(false) auf, muss man sich selbst um die Freigaben der Items kümmern. Um eine Kopie eines Items zu bekommen, musst Du dieses Object TCarPos noch z.b. um die funktionen AssignTo und Clone erweitern:
Delphi-Quellcode:
Dann machst Du einfachTCarPos public procedure AssignTo(_Dest : TCarPos); function Clone : TCarPos; end; procedure TCarPos.AssignTo(_Dest : TCarPos); begin _Dest.Zeitpunkt := Zeitpunkt; ... end; function TCarPos.Clone : TCarPos; begin Result := TCarPos.Create; AssignTo(Result); end;
Delphi-Quellcode:
schon hast Du eine Kopie, die Du mit slave.clear wieder löschst.for i := 0 to master.count-1 do slave.add(master[i].clone) idealer Weise erweiterst Du Deine Objektlist auch um AssignTo und Clone um sich die Schleife zu sparen |
Re: Kopie eines Item aus der TObjectList
ich mache mich sofort an die Arbeit.
Tausend Dank und schöne Grüße. Kostas |
Re: Kopie eines Item aus der TObjectList
Hallo sH17,
es funkt beste Sahne mit dem Clonen. Hab auch die constructoren aus beiden TObjectList entfernt. Ein bisschen unwohl ist mir noch bei dieser Sache, weil ich noch nicht sattelfest bin in OOP. (Ich habe es bis jetzt umgehen können. ;-)) Wenn ich das free der TObjectList aufrufe werden dann auch alle geklonte items gelöscht? Ist es eigentlich Möglich memory leaks zu finden? Hier noch meine drei Klassen. Wenn es Dir möglich währe nochmals drüber zu schauen. Besten Dank nochmals sH17 und schöne Grüße.
Delphi-Quellcode:
TCarPos = class(TObject)
private FZeitpunkt:TDateTime; FCarID:integer; Procedure SetZeitpunkt(value :TDateTime); function GetZeitpunkt:TDateTime; Procedure SetCarID(value :Integer); function GetCarID:Integer; public constructor Create; property Zeitpunkt: TDateTime read GetZeitpunkt write SetZeitpunkt; property CarID: Integer read GetCarID write SetCarID; procedure AssignTo(var Dest : TCarPos); function Clone: TCarPos; end; TCarPosCollection =Class(TObjectList) private FZustand:Boolean; function Get(Index: Integer): TCarPos; public procedure Add(Item: TCarPos); property Items[Index: Integer]: TCarPos read Get; procedure AssignTo(var Dest : TCarPosCollection); function Clone: TCarPosCollection; end; TTagesauswertung =Class(TObjectList) private function Get(Index: Integer): TCarPosCollection; public procedure Add(Item: TCarPosCollection); property Items[Index: Integer]: TCarPosCollection read Get; end; { TCarPos } constructor TCarPos.Create; begin FZeitpunkt:=0.0; FCarID:=0; end; procedure TCarPos.AssignTo(var Dest: TCarPos); begin Dest.FZeitpunkt := FZeitpunkt; Dest.FCarID := FCarID; end; function TCarPos.Clone: TCarPos; begin result := TCarPos.Create; AssignTo(result); end; { TCarPosCollection } procedure TCarPosCollection.Add(Item: TCarPos); begin inherited Add(Item); end; function TCarPosCollection.Get(index: integer):TCarPos; begin result := inherited Get(Index); end; procedure TCarPosCollection.AssignTo(var Dest: TCarPosCollection); var i:integer; begin Dest.FZustand := FZustand; {kopiere alle items vom typ TCarPos} for i := 0 to count-1 do Dest.add(items[i].clone); end; function TCarPosCollection.Clone: TCarPosCollection; begin result := TCarPosCollection.Create; AssignTo(result); end; { TTagesauswertung } procedure TTagesauswertung.Add(Item: TCarPosCollection); begin inherited Add(Item); end; function TTagesauswertung.Get(index: integer):TCarPosCollection; begin result := inherited Get(Index); end; |
Re: Kopie eines Item aus der TObjectList
Ich sehe soweit keine Probleme. Sollte alles so klappen. Die Add() Funktion ist nicht unbedingt nötig - ansonsten aber auch nicht falsch.
|
Re: Kopie eines Item aus der TObjectList
Solange TObjectList.Create(true) aufgerufen wurde, werden bei Free auch die Items freigegeben.
Noch eine Anmerkung zu
Delphi-Quellcode:
In diesem Fall ist die Verwendung von Dest.FZeitpunkt und Dest.FCarID kein Problem, da die Set-Methoden der Properties Zeitpunkt und CarID auch nix anderes machen. Sollte allerdings in den Set-Methoden weiterer Code stehen, der mit dem Wert vorher noch etwas macht, dann musst Du folgendes aufrufen:
procedure TCarPos.AssignTo(var Dest: TCarPos);
begin Dest.FZeitpunkt := FZeitpunkt; Dest.FCarID := FCarID; end;
Delphi-Quellcode:
Bei
procedure TCarPos.AssignTo(var Dest: TCarPos);
begin Dest.Zeitpunkt := Zeitpunkt; Dest.CarID := CarID; end;
Delphi-Quellcode:
wäre ggf noch ein Dest.Clear zu Beginn sinnvoll.
procedure TCarPosCollection.AssignTo(var Dest: TCarPosCollection);
var i:integer; begin Dest.FZustand := FZustand; {kopiere alle items vom typ TCarPos} for i := 0 to count-1 do Dest.add(items[i].clone); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:52 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