AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist
Thema durchsuchen
Ansicht
Themen-Optionen

Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist

Ein Thema von norwegen60 · begonnen am 14. Sep 2023 · letzter Beitrag vom 15. Sep 2023
Antwort Antwort
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
509 Beiträge
 
Delphi 12 Athens
 
#1

Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist

  Alt 14. Sep 2023, 13:54
Hallo zusammen

ich habe vereinfacht folgende Klassen struktur:
Delphi-Quellcode:
Tvalues:Class
  x:Double;
  y:Double;
end;

TTest:Class
  Name:String;
  Values:TValues;
end;

TTestListList = class(TObjectList<TTest>)
Es kann es sein, dass mehrere TTest auf das gleich TValues zeigen

Jetzt will ich in allen TTest, denen ein TValues zugewiesen ist, dieses löschen

Delphi-Quellcode:
for i := 0 to TestList.Count do
  if (TestList[i].Values <> nil) then
    TestList[i].Values.Free;
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.
Einfach TestList[i].Values := nil; ist auch keine gute Lösung, da ich dann lauter Leichen rum liegen habe
Mir alle TValues merken und sie, nachdem ich alle TestList[i].Values := nil gesetzt habe, scheint mir aufwändig

Wie aber kann ich TValues löschen (Free) und dann auch merken, dass der bereits gelöscht wurde.

Danke
Gerd
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.655 Beiträge
 
Delphi 12 Athens
 
#2

AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist

  Alt 14. Sep 2023, 14:06
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.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
509 Beiträge
 
Delphi 12 Athens
 
#3

AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist

  Alt 14. Sep 2023, 14:34
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:
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;
Oder geht es einfacher

Geändert von norwegen60 (14. Sep 2023 um 14:46 Uhr) Grund: TestList[i].Values:=Nil statt Free
  Mit Zitat antworten Zitat
Edelfix

Registriert seit: 6. Feb 2015
Ort: Stadtoldendorf
220 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist

  Alt 14. Sep 2023, 15:12
Delphi-Quellcode:
for i := 0 to TestList.Count do
  if (TestList[i].Values <> nil) then
    FreeAndNil(TestList[i].Values);
  Mit Zitat antworten Zitat
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
509 Beiträge
 
Delphi 12 Athens
 
#5

AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist

  Alt 14. Sep 2023, 15:28
[DELPHI]
for i := 0 to TestList.Count do
if (TestList[i].Values <> nil) then
FreeAndNil(TestList[i].Values);
Das habe ich als erstes probiert. Das lässt Delphi nicht zu
Code:
[DCC Fehler] uQualHelper.pas(187): E2197 Konstantenobjekt kann nicht als Var-Parameter weitergegeben werden
  Mit Zitat antworten Zitat
jziersch

Registriert seit: 9. Okt 2003
Ort: München
258 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist

  Alt 15. Sep 2023, 10:06
Zitat:
Es kann es sein, dass mehrere TTest auf das gleich TValues zeigen
In diesem Fall würde ich eine separate Liste anlegen in denen die TValues + eine eindeutige ID (Cardinal) gespeichert werden. In deiner TTest Klasse hast Du dann nur diese ID.
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 ?
WPCubed GmbH
Komponenten für Delphi:
WPTools, wPDF, WPViewPDF
  Mit Zitat antworten Zitat
mytbo

Registriert seit: 8. Jan 2007
478 Beiträge
 
#7

AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist

  Alt 15. Sep 2023, 18:04
Wie aber kann ich TValues löschen (Free) und dann auch merken, dass der bereits gelöscht wurde.
Eine weitere Möglichkeit ist, das Values-Objekt mit einer Referenzzählung auszustatten:
Delphi-Quellcode:
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;
Bis bald...
Thomas

Geändert von mytbo (15. Sep 2023 um 18:07 Uhr) Grund: Tippfehler korrigiert
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

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

AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist

  Alt 15. Sep 2023, 19:42
Eine weitere Möglichkeit ist, das Values-Objekt mit einer Referenzzählung auszustatten
Würde das nicht lediglich verhindern, dass die TValues Instanz vorab freigegeben wird? Damit umgeht man das Problem zwar (in dem gezeigten Beispiel durchaus valide), löst es aber nicht wirklich.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist

  Alt 15. Sep 2023, 19:46
[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.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
mytbo

Registriert seit: 8. Jan 2007
478 Beiträge
 
#10

AW: Wie kann ich feststellen, ob Sub-Klasse schon gelöscht ist

  Alt 15. Sep 2023, 20:06
Eine weitere Möglichkeit ist, das Values-Objekt mit einer Referenzzählung auszustatten
Würde das nicht lediglich verhindern, dass die TValues Instanz vorab freigegeben wird? Damit umgeht man das Problem zwar (in dem gezeigten Beispiel durchaus valide), löst es aber nicht wirklich.
Ich habe den Eröffnungspost noch mal gelesen und interpretiere, dass er mit Löschen vermutlich Values-Objekt nilen meint und erst, wenn es ohne Referenz ist, ableben soll. Mein Bezug ist der vorletzte Absatz des Posts. Vielleicht vermute ich falsch.

Bis bald...
Thomas
  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 02:18 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 by Thomas Breitkreuz