![]() |
AW: tlist. get "überschreiben", Fehlermeldung verhindern
Hi,
@himitsu: meine obigen Änderungen schlagen wohl alle in das von dir zu vermeidende Kontor. Diese Gleichsetzung geht tatsächlich. Ja, meine txyz sind Ableitungen von tobject. Bis jetzt funktionieren alle Routinen - warum ich mich von tobjectlist wieder abgewendet habe, weiß ich nicht mehr - könnte das aber wieder aufnehmen. zu Generics - zugegebnermaßen kenne ich diese Schreibweise gar nicht - kann ich auch nicht so schreiben - kommt Fehler tlist<> unbekannt.
Delphi-Quellcode:
Gruß Uwetype TXyzList = class(TList<TXyz>) function TryGet(idx: Integer; out obj: TXyz); end; //bei mir TMyList1 = class(TList<Tobj1>) function TryGet(idx: Integer; out obj: Ttobj1); //läßt sich nicht kompilieren |
AW: tlist. get "überschreiben", Fehlermeldung verhindern
Du mußt natürlich noch die passende Unit einbinden. :zwinker:
siehe ![]() |
AW: tlist. get "überschreiben", Fehlermeldung verhindern
Hi,
ok, mit Generics.collections habe ich mich noch nie beschäftigt. Bisher habe ich tlist von unit classes verarbeitet! Generics.collections.tlist kann man den verarbeiteten Zeigertyp festlegen - geht das auch mit Objecten? Werden diese bei .destroy (.free gibts wohl nicht) mit freigegeben? In classes.tlist gibt's procedure Notify(Ptr: Pointer; Action: TListNotification); die überschrieben werden kann. in generics ist das eine Eigenschaft Fragen über Fragen ... da Muß ich erst mal 'ne Weile lesen. Bleibt trotzdem meine Anfrage der abgeleiteten Listen mit abgeleiteten Objekten übrig. probiert: tmylist1=class(generics.collections.tobjectlist<tm yobj1>) end; nicht erlaubt: tmylist2=class(generics.collections.tmylist1<tmyob j2>) end; man ist also auf den einmalo festgelegten Datentyp festgenagelt - oder? Gruß Uwe |
AW: tlist. get "überschreiben", Fehlermeldung verhindern
Bei TObjectList ist die Notification schon fertig überschrieben.
Man kann im Constructor oder später über OwnsObjects festlegen, ob die enthaltenen Objekte freigegeben werden sollen. .Free gibt es immer, denn das ist im Basistyp "TObject" deklatiert, von dem jede Klasse erbt. Destroy besser nicht direkt aufrufen. (das wird dann intern vom Free aufgerufen) Nun ja, das ist ja grade der Grund/Vorteil ... - man muß nicht mehr casten und kann sich dabei auch nicht mehr vertun - wenn man außerhalb keine "bösen" Casts macht, dann kann man ganz einfach davon ausgehn, daß in der Liste immer nur die vorgegebenen Objekte drinnen sind. Wie bei der restlichen Vererbung gilt auch hier: - Es können die angegebenen Typen/Klassen/Objekte in diese Listen rein und alle Nachfahren Eine
Delphi-Quellcode:
ist also eine Art
TList<xyz>
Delphi-Quellcode:
(PS:
array of xyz
Delphi-Quellcode:
), mit ein paar mehr Features/Hilfsfunktionen.
TArray<xyz>
Man kann sich dsa teilweise sehr viel sparen. (versuch mal das Selbe mit einer normalen TList + Record-Pointer + New + Dispose + Notify überschreiben oder mit einer TObjectList + TXyz als Objekt, inkl. Create und Co.)
Delphi-Quellcode:
Den Namespace in generics.collections.tlist kannst du weglassen. (Delphi weiß anhand des <...>, ob generisch oder nicht).
type
TXyz = record s: string; i: Integer; end; var Liste: TList<TXyz>; X: TXyz; Z: Integer; begin Liste := TList<TXyz>.Create; try X.s := 'abc'; X.i := 123; Liste.Add(X); X.s := 'def'; X.i := 456; Liste.Add(X); X.s := 'xyz'; X.i := 789; Liste.Add(X); for Z := 0 to Liste.Count - 1 do WriteLn(X[Z].s, X[Z].i); for X in Liste do WriteLn(X.s, X.i); finally Liste.Free; end; Tipp: Es gibt ganz viele Turorial-Videos bei Emba, Youtube und Co. Zitat:
In eine Variable TMemo bekommst du ja auch keine TButton rein. (offiziell und ohne böse Casts) Zitat:
|
AW: tlist. get "überschreiben", Fehlermeldung verhindern
Hi,
@himitsu: Danke, ich habe wohl übersehen, das tlist.free nicht automatisch die eingelagerten Elemente und ihren Speicher löscht (?!) das macht tobjectlist mit Voreinstellung ownsobjecrts=true. Deiner Anmerkung: Wie bei der restlichen Vererbung gilt auch hier: - Es können die angegebenen Typen/Klassen/Objekte in diese Listen rein und alle Nachfahren kann ich nicht folgen
Delphi-Quellcode:
ist nicht erlaubt.
tmyobj1=class(tobject)
end; tmyobj2=class(tmyobj1) end; TMyList1 = class(TobjectList<tmyobj1>) end; TMyList2 = class(TobjectList<tmyobj2>) end; nur so:
Delphi-Quellcode:
da kann ich sicher tmyobj2 durch add einfügen (du schreibst ja, daß das geht), bekomme aber von get oder items[idx] nur tmyobj1,
TMyList2 = class(TobjectList)
end; würde aber gerne in tmylist2 auch auf tmyobj2 zugreifen, welche ich dort speichern möchte. habe nun folgendes erfolgreich getestet - bleibt die frage, ob das wieder ein böses casting ist (erst mal für tobjectlist, dürfte aber genauso für die generischen gehen):
Delphi-Quellcode:
Wenn ich dafür sorge, das nur tobj1 in die Liste reinkommen, kann ich nun ohne Typcasting auf die Einträge zugreifen, muß
TMyList1 = class(TObjectList) {verwaltet tobj1}
private protected public function Get(Index: Integer): tmyobj1;virtual;//redefiniert die statische Methode, jetzt wird tobj1 statts pointer zurückgegeben end; function TMyList1.Get(Index: Integer): tmyobj1; begin result:=inherited get(index); //if cardinal(index) < Cardinal(Count) then // Result := List^[Index] else result:=nil; end; aber für alle Lesezugriffe .get benutzen (nicht etwa .items[idx]) - das ist sicher ein Nachteil. In einer abgheleiteten Liste mit von tmyobj1 abgeleiteten Elementen und überschriebenem .get könnte ich dann auf die abgeleiteten Elemente zugreifen und auf die schon vorhandenwen Funktionen von der Vorgängerliste. Oder ist das auch zu sehr um die Ecke gedacht? in deinem Beispiel geht das nicht for Z := 0 to Liste.Count - 1 do WriteLn(X[Z].s, X[Z].i); x(z).s gibt's nicht das ist beeindruckend for X in Liste do WriteLn(X.s, X.i); finally gibt free hier auch die Einträge selbst frei??? Liste.Free; Grüße Uwe |
AW: tlist. get "überschreiben", Fehlermeldung verhindern
Zitat:
|
AW: tlist. get "überschreiben", Fehlermeldung verhindern
Hi,
nachdem ich noch dies und jenes getestet habe, möchte ich für mich das Thema abschließen und "Erkenntnisse" zusammenfassen. 1. Ok, mann sollte aus tlist.get die Fehlermeldung nicht rausnehmen 2. Wenn man in tlist Angst vor Fehlgriffen hat, sollte man eine Sicherheitsroutine an kritischen Stellen einrichten alà
Delphi-Quellcode:
3. spezifizierte Listen: Für Speicherung spezieller Datenstrukturen in Listen sind die Generics (tlist<>)bestens geeignet, der Zugriff auf die Elemente ist dann ohne "wilde" Typeumwandlungen möglich - aber
function TMyList.ValidIndex(aindex: integer): boolean;
begin result:= cardinal(aindex)<cardinal(Count) //cardinal <-1 ergibt immer eine Zahl größer als cardinal einer positiven Zahl end; 4. Will ich Vererbung sowohl der Elemente als auch der Listen realisieren komme ich ohne Typumwandlung an irgendeiner Stelle nicht aus:
Delphi-Quellcode:
TMyList2withmyobj2 soll sowohl .verarbeiteA als auch .verarbeiteAundB können.
tmyobj1=class(tobject)
A:integer; end; tmyobj2=class(tmyobj1) B:string; end; TMyList1withtmyobj1 = class(TobjectList) function Get(Index: Integer): tMyobj1;virtual; procedure verarbeiteA; end; TMyList2withmyobj2 = class(TMyList1withtmyobj1) function Get(Index: Integer): tMyobj2;override; procedure verarbeiteAundB; end; function TMyList1withtmyobj1.Get(Index: Integer): tmyobj1; begin result:=tmyobj1(inherited get(index)); //result:=inherited get(index); ginge auch bei direkten Naschfahren von tlist end; function TMyList2withtmyobj2.Get(Index: Integer): tmyobj2; begin result:=tmyobj2(inherited get(index)); end; TMyList1withmyobj1 währe noch generisch am einfachsten, aber danach nicht mehr. Darum füge ich eine Methode hinzu, die mir die richtigen Objecte liefert, hier überschreibe ich .get. Ist das dann 'ne "wilde Typumwandlung"? Der Übergang von tlist nach tobjectlist geht in der Unit cntnrs ähnliche Wege:
Delphi-Quellcode:
function TObjectList.GetItem(Index: Integer): TObject;
begin Result := inherited Items[Index]; end; function TObjectList.First: TObject; begin Result := TObject(inherited First); end; //oder gar items selbst property Items[Index: Integer]: TObject read GetItem write SetItem; default; gerade schnell noch probiert: property Items[Index: Integer]: TMyobj1 read GetItem write SetItem; default; procedure SetItem(Index: Integer; AObject: tMyObj1); function GetItem(Index: Integer): TMyObj1; . . . function TMyList1withtmyobj1.GetItem(Index: Integer): TMyObj1; begin Result := TMyObj1(inherited Items[Index]); end; procedure TMyList1withtmyobj1.SetItem(Index: Integer; AObject: TMyObj1); begin inherited Items[Index] := AObject; end; so braucht man .get nicht zu definieren und kann wie gwohnt auf items zugreifen Danke allen Diskutanten Grüße Uwe |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:26 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