![]() |
Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist
Hallo zusammen
ich habe vereinfacht folgende Klassen struktur:
Delphi-Quellcode:
Es kann es sein, dass mehrere TTest auf das gleich TValues zeigen
Tvalues:Class
x:Double; y:Double; end; TTest:Class Name:String; Values:TValues; end; TTestListList = class(TObjectList<TTest>) Jetzt will ich in allen TTest, denen ein TValues zugewiesen ist, dieses löschen
Delphi-Quellcode:
Da Free Values nicht auf nil setzt, schlägt die Prüfung gegen nil beim nächsten TTest mit demselben TValues fehl und Delphi hängt sich beim nochmaligen Value.Free auf.
for i := 0 to TestList.Count do
if (TestList[i].Values <> nil) then TestList[i].Values.Free; Einfach
Delphi-Quellcode:
ist auch keine gute Lösung, da ich dann lauter Leichen rum liegen habe
TestList[i].Values := nil;
Mir alle TValues merken und sie, nachdem ich alle
Delphi-Quellcode:
gesetzt habe, scheint mir aufwändig
TestList[i].Values := nil
Wie aber kann ich TValues löschen (Free) und dann auch merken, dass der bereits gelöscht wurde. Danke Gerd |
AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist
Das ist eben das Problem bei Mehrfachreferenzen. Entweder man stellt komplett auf Interfaces um oder ernennt eine "Masterliste", welche dann Owner der enthaltenen Objekte ist. Weitere Listen werden dann mit OwnsObjects auf false erzeugt, damit es nicht knallt, wenn diese wieder freigegeben werden.
|
AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist
Mmh, Mist. Und ich hatte gehofft, dass es einen Weg gibt umd festzustellen, dass ein Object gefreet wurde.
In Ermanglung von Interface-Wissen würde ich es so machen:
Delphi-Quellcode:
Oder geht es einfacher
ValueList := TValueList.Create(True);
try for i := 0 to TestList.Count do if (TestList[i].Values <> nil) then begin bExist:=False; for j:=0 to ValueList.Count-1 do begin // Hier bin ich mir nicht ganz sicher, ob ich es mir so einfach machen kann. // Ich habe es schon mal so gemacht und es hat funktioniert. Aber ist es sicher? if (ValueList[j] = TestList[i].Values) then bExits:= True; if bExist then break; end; if not bExist then ValueList.Add(TestList[i].Values); TestList[i].Values := Nil; end; finally ValueList.Free; end; |
AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist
Delphi-Quellcode:
for i := 0 to TestList.Count do
if (TestList[i].Values <> nil) then FreeAndNil(TestList[i].Values); |
AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist
Zitat:
Code:
[DCC Fehler] uQualHelper.pas(187): E2197 Konstantenobjekt kann nicht als Var-Parameter weitergegeben werden
|
AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist
Zitat:
Jede neues TValue erzeugt eine neue ID mit Inc(LastID). Wenn Du ein TValue löscht werden die IDs automatisch ungültig. Dies Liste ist sortiert, da neue Values hinten angehängt werden. Wert-Lücken ergeben sich durch das löschen. Du kannst das TValue zu jeder ID schnell mit List.BinarySearch suchen - und wenn es nicht gefunden wird, ist der Wert eben ungültig. Anmerkung - müsste es nicht heißen for i:=0 to List-Count-1 do ? |
AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist
Servus,
Zitat:
Wer Objekte anlegt, der gibt die auch wieder frei (keine Regel ohne Ausnahme). D.h. du kannst so vorgehen wie jziersch vorschlägt. Oder du sagst etwas mehr darüber wie die KLassen zueinander finden. ein FreeAndNil funktioniert nicht, weil die Funktion eben einen Var-Parameter braucht. Lösen kannst Du das mit einem Zweizeiler:
Delphi-Quellcode:
allerdings klappt das im weiteren Verlauf nicht weil:
for i := 0 to TestList.Count do
if (TestList[i].Values <> nil) then begin TestList[i].Values.Free; TestList[i].Values := nil; end Zitat:
Grüße |
AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist
Eine ziemlich bequeme Möglichkeit wäre es, die Klassen von
Delphi-Quellcode:
abzuleiten und mit
TComponent
Delphi-Quellcode:
zu arbeiten. Das könnte dann in etwa so aussehen:
FreeNotification
Delphi-Quellcode:
Die verbleibenden public Fields würde ich aber gleich auch noch in Properties umwandeln.
type
TValues = class(TComponent) public x: Double; y: Double; end; TTest = class(TComponent) public Name: String; private FValues: TValues; procedure SetValues(const Value: TValues); protected procedure Notification(AComponent: TComponent; Operation: TOperation); override; public property Values: TValues read FValues write SetValues; end; procedure TTest.Notification(AComponent: TComponent; Operation: TOperation); begin if (AComponent = FValues) and (Operation = opRemove) then FValues := nil; inherited; end; procedure TTest.SetValues(const Value: TValues); begin if FValues <> Value then begin if FValues <> nil then FValues.RemoveFreeNotification(Self); FValues := Value; if FValues <> nil then FValues.FreeNotification(Self); end; end; |
AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist
Zitat:
Delphi-Quellcode:
Bis bald...
type
TValues = class(TObject) strict private FRefCount: Integer; private FX: Double; FY: Double; public constructor Create(pmX, pmY: Double); reintroduce; procedure IncReference; procedure DecReference; property X: Double read FX; property Y: Double read FY; end; TTest = class(TObject) private FName: String; FValues: TValues; procedure FreeValues; procedure SetValues(pmValues: TValues); public constructor Create(const pmcName: String); reintroduce; destructor Destroy; override; property Name: String read FName; property Values: TValues read FValues write SetValues; end; TTestList = class(TObjectList<TTest>) public procedure FreeAllValues; end; constructor TValues.Create(pmX, pmY: Double); begin inherited Create; FX := pmX; FY := pmY; end; procedure TValues.IncReference; begin Inc(FRefCount); end; procedure TValues.DecReference; begin Dec(FRefCount); if FRefCount = 0 then Self.Free; end; constructor TTest.Create(const pmcName: String); begin inherited Create; FName := pmcName; end; destructor TTest.Destroy; begin FreeValues; inherited Destroy; end; procedure TTest.FreeValues; begin if FValues <> Nil then begin var v: TValues := FValues; FValues := Nil; v.DecReference; end; end; procedure TTest.SetValues(pmValues: TValues); begin FreeValues; if pmValues <> Nil then begin pmValues.IncReference; FValues := pmValues; end; end; procedure TTestList.FreeAllValues; begin for var i: Integer := 0 to Count - 1 do Items[i].Values := Nil; end; var v: TValues; t: TTest; begin v := TValues.Create(1, 2); t := TTest.Create('A'); t.Values := v; FList.Add(t); t := TTest.Create('B'); t.Values := v; FList.Add(t); FList.FreeAllValues; Thomas |
AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist
Zitat:
|
AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist
[Weak]-Referenzen, geht auch in Arrays oder so mancher generischen Liste.
Die würden auf NIL gesetzt, wenn das Objekt freigegeben wird. Alternativ ein Callback, welcher beim Löschen das auf NIL setzt, bzw. den Eintrag aus der Liste entfernt. * kann man sich selbst bauen * oder man nutzt z.B. die Free-Notification des TComponent. |
AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist
Zitat:
Bis bald... Thomas |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:45 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