AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Anzeigen wenn sich in TObjectList ein Eintrag geändert hat
Thema durchsuchen
Ansicht
Themen-Optionen

Anzeigen wenn sich in TObjectList ein Eintrag geändert hat

Ein Thema von norwegen60 · begonnen am 3. Apr 2021 · letzter Beitrag vom 5. Apr 2021
Antwort Antwort
Benutzerbild von Uwe Raabe
Uwe Raabe

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

AW: Anzeigen wenn sich in TObjectList ein Eintrag geändert hat

  Alt 3. Apr 2021, 10:13
Versuch's mal so:
Delphi-Quellcode:
    if (FParentObject is TBaseObjectList<TBase>) then
      TBaseObjectList<TBase>(FParentObject).Changed := true;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

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

AW: Anzeigen wenn sich in TObjectList ein Eintrag geändert hat

  Alt 3. Apr 2021, 10:16
Konsequenterweise sollte man die Liste auch so deklarieren: TBaseObjectList<T: TBase>
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
norwegen60

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

AW: Anzeigen wenn sich in TObjectList ein Eintrag geändert hat

  Alt 3. Apr 2021, 12:33
Vielen Dank
Mit den Änderungen lässt sich das Testprojekt jetzt compilieren. Aber zwei Dinge treten noch auf
  • Die Abfrage (FParentObject is TBaseObjectList<TBase>) bringt kein TRUE zurück, obwohl ich lNamen.ParentObject := lNamenList; zugewiesen habe
  • Spätestens wenn ich das Programm beende, kommt ein EAccessViolation auf. Kann aber auch schon passieren, wenn ich aus dem Programm in die IDE wechsle.

Ich bin nicht sicher, ob ich den Zusatz richtig verstanden habe
Konsequenterweise sollte man die Liste auch so deklarieren: TBaseObjectList<T: TBase>
Ich habe es auf verschiedene Arten probiert, das Verhalten blieb aber immer gleich
Delphi-Quellcode:
  TBaseObjectList<T: class> = class(TObjectList<T>)
  TBaseObjectList<T: TBase> = class(TObjectList<T>)
  TBaseObjectList<TBase: class> = class(TObjectList<TBase>)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Anzeigen wenn sich in TObjectList ein Eintrag geändert hat

  Alt 3. Apr 2021, 13:38
Problem ist, dass bei den Generics die Vererbung bissl "komisch" arbeitet und die Hierarchie nicht immer so aussieht, wie man denken könnte.


Aber ich hätte auch gedacht, dass es bei diesen 3 Varianten hätte gehen sollen, da du eigentlich auf den gleichen selben Typ prüfst und der ja gleich sein müsste.
Wobei 1 und 3 das Selbe ist, von den Typen her, da sich nur der Bezeichner unterscheidet. (ob es A oder B heißt, macht keinen Unterschied)
[EDIT] Das TBase in is ...<TXyz> war doch das TXyz aus TBaseObjectList<TXyz: class> = ... und nicht das "einzelne" TBase = class ?

Aber bei TBaseObjectList<T: TBase> = class(... ist diese Prüfung auch nicht nötig, da bereits der Compiler die Prüfung übernimmt und du somit einfach "blind" hart casten kannst, weil es nichts Anderes sein kann.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu ( 3. Apr 2021 um 14:36 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

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

AW: Anzeigen wenn sich in TObjectList ein Eintrag geändert hat

  Alt 3. Apr 2021, 16:54
So sollte es auf der sicheren Seite sein:
Delphi-Quellcode:
type
  TBase = class;
  TBaseObjectList = class(TObjectList<TBase>)
  private
    FChanged: Boolean;
  public
    constructor Create(AOwnsObjects: Boolean = True); overload;
    property Changed: Boolean read FChanged write FChanged;
  end;
  TBaseObjectList<T: TBase> = class(TBaseObjectList);
Dann kannst du auch wieder auf TBaseObjectList prüfen und casten:
Delphi-Quellcode:
procedure TBase.SetChanged(const Value: Boolean);
begin
  if FChanged <> Value then begin
    FChanged := Value;
    if (FParentObject is TBaseObjectList) then
      TBaseObjectList(FParentObject).Changed := True;
  end;
end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
norwegen60

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

AW: Anzeigen wenn sich in TObjectList ein Eintrag geändert hat

  Alt 3. Apr 2021, 18:56
Ich bin nicht sicher ob jetzt ein Teil meiner Anforderung verloren gegangen ist.

So wie TBase die Basisklasse für meine kommenden Objekte ist, sollte TBaseObjectList die Basisklasse für meine kommenden Listen sein

Eine der kommenden Klasse incl. Liste könnte dann so aussehen
Delphi-Quellcode:
  // ***************************************************************************************************************************************
  // Als Beispiel eine auf ein eigenes Property abgespeckte Klasse
  TNamen = class(TBase)
  private
    FNamen: String;
    procedure SetNamen(const Value: String);
  public
    property Namen: String read FNamen write SetNamen;

    constructor Create;
    destructor Destroy; override;
  end;

  // ***************************************************************************************************************************************
  // Und die zu diesem Beispiel passen ObjectList
  TNamenList<T: TNamen> = class(TBaseObjectList);

var
  lNamenList: TNamenList;
Wenn ich es so definiere TNamenList<T: TNamen> = class(TBaseObjectList) sagt Delphi bei Zugriff auf lNamenList[3].Namen dass er Namen nicht kennt

Wenn ich es so definiere TNamenList = TBaseObjectList<TNamen>; sagt Delphi bei Zugriff auf lNamen := lNamenList[3]; dass TNamen und TBase incompatibel sind.

Wenn ich per Typecast lNamen := TNamen(lNamenList[3]); auf die Liste zugreife funktioniert die Änderung von lNamen.Namen und die Liste wird korrekt auf Changed gesetzt. Eigentlich wollte ich aber ohne TypeCast auskommen, zumal es viele Zugriffe gibt die direkt auf lNamenList[3].Namen zugreifen. Und beim Beenden des Programms kommt weiterhin der EAccessViolation.


Das hier verstehe ich nicht ganz
Delphi-Quellcode:
  TBaseObjectList = class(TObjectList<TBase>)
  private
  ...
  end;
  TBaseObjectList<T: TBase> = class(TBaseObjectList);
Soll es wirklich zwei mal TBaseObjectList heißen?

Ich habe mal mein Testcode angehängt. Hängt vielleicht nur noch an einer Kleinigkeit
Angehängte Dateien
Dateityp: 7z Source.7z (4,5 KB, 2x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

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

AW: Anzeigen wenn sich in TObjectList ein Eintrag geändert hat

  Alt 3. Apr 2021, 22:26
Ja, stimmt. Der generische Part der TObjectList<T> geht damit verloren. Wenn du das nicht nachbilden und trotzdem bei dem Ansatz mit dem ParentObject bleiben willst, kannst du entweder den HardCast auf TObjectList<TBase> vom Anfang machen oder über über ein OnChanged-Event oder ein Interface arbeiten.

Eine ganz andere Alternative wäre auch ein Message-Mechanismus:
Delphi-Quellcode:
const
  cNotifyChanged = 1;

type
  TBase = class;
  TBaseObjectList<T: TBase> = class(TObjectList<T>)
  private
    FChanged: Boolean;
  protected
    procedure NotifyChanged(var Message: TDispatchMessage); message cNotifyChanged;
  public
    property Changed: Boolean read FChanged write FChanged;
  end;

...

procedure TBase.SetChanged(const Value: Boolean);
var
  msg: TDispatchMessage;
begin
  if FChanged <> Value then begin
    FChanged := Value;
    msg.MsgID := cNotifyChanged;
    FParentObject.Dispatch(msg);
  end;
end;

...

procedure TBaseObjectList<T>.NotifyChanged(var Message: TDispatchMessage);
begin
  Changed := True;
end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  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 16:53 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