![]() |
generische ObjectList: Löschen eines Elementes
Hallo,
ich hab mal eine Verständnisfrage. Ich habe eine generische ObjectList:
Delphi-Quellcode:
.
ObjectList_sichtbare_Masken := TObjectList<TMaskeFeld>.Create(false);
In dieser Procedure wird aus der Liste gelöscht:
Delphi-Quellcode:
Früher hatte ich keine generische ObjectList, sonder eine normale ObjectList
procedure Masken_ausblenden(akt_MaskID: String);
var i : Integer; MaskeFeld: TMaskeFeld; begin for MaskeFeld in ObjectList_sichtbare_Masken do If MaskeFeld.NameID <> akt_MaskID then begin MaskeFeld.Visible := false; i := ObjectList_sichtbare_Masken.IndexOf(MaskeFeld); ObjectList_sichtbare_Masken.Delete(i); end; end;
Delphi-Quellcode:
und hab so gelöscht:
ObjectList_sichtbare_Masken := TObjectList.Create(false);
Delphi-Quellcode:
(grob aus dem Gedächtnis getippt - hab leider den originalen Code nicht mehr)
procedure Masken_ausblenden(akt_MaskID: String);
var i : Integer; MaskeFeld: TMaskeFeld; begin for Pred(ObjectList_sichtbare_Masken.Count) downto 0 do begin MaskeFeld := TMaskeFeld(ObjectList_sichtbare_Masken.Items[i]); If MaskeFeld.NameID <> akt_MaskID then begin MaskeFeld.Visible := false; ObjectList_sichtbare_Masken.Delete(i); end; end; end; "Früher", also bei der normalen ObjectList musste man ja die for-Schleife rückwärts laufen lassen, wenn man ein Element löschen will, da sich ja durch das Löschen die Anzahl ändert. Aber warum brauch ich das bei der generischen ObjectList nicht mehr? Ich kann es mir nur so erklären, dass ich in der Schleife direkt ein Object bekomme und nicht, wie früher, einen Index. |
AW: generische ObjectList: Löschen eines Elementes
Also bei C# darfst Du die Liste nicht verändern, während Du durch sie durch iterierst. Hier ist das vermutlich anders.
Aber sag mal, findest Du das nicht ein wenig umständlich, durch die Liste mit einem Iterator zu laufen, den Index zu ermitteln und dann zu löschen. Das ist doch viel langsamer als eine Schleife.
Delphi-Quellcode:
Nur weil es das 'for in' gibt, muss man es doch nicht immer verwenden...
For i:= myList.Count-1 downto 0 do
if EntryIsNotValid(myList[i]) then myList.Delete(i); |
AW: generische ObjectList: Löschen eines Elementes
Zitat:
|
AW: generische ObjectList: Löschen eines Elementes
Du musst dir nur einen Enumerator basteln, der halt rückwärts durch die Liste läuft. (
Delphi-Quellcode:
)
for MaskeFeld in ObjectList_sichtbare_Masken.Reverse do
(den gibt es nur standardmäßig nicht im fertig in die Delphi-Listen eingebaut :stupid: , so wie es auch keine Filter gibt :wall: ) oder du arbeitest mir einem Zwischenspeicher, so ala
Delphi-Quellcode:
.
for MaskeFeld in ObjectList_sichtbare_Masken.ToArray do
Und dann gibt es auch noch generische Listen von anderen Leuten, die sowas und mehr drin haben. |
AW: generische ObjectList: Löschen eines Elementes
die Procedure mit der generischen Liste funktioniert ja sehr gut
Nur frage ich mich, warum das so problemlos geht |
AW: generische ObjectList: Löschen eines Elementes
Zitat:
Warum muss man das nicht machen? Weil der Iterator immun dagegen ist, das Du ihm das aktuelle Objekt unter dem Hintern wegziehst, vielleicht. Und warum? Dazu musst Du in die Implementierung schauen, vermutlich prüft er jedes mal, ob noch Elemente da sind. Oder das funktioniert erst gar nicht, weil der Delphi-Iterator gar nicht merkt, das die Liste verändert wird. Was passiert denn, wenn Du eine Liste mit zwei Element hast und dann deine Schleife startest? Sind beide Elemente weg? |
AW: generische ObjectList: Löschen eines Elementes
ich merkt halt dahingegen dass es funktioniert, dass die MaskeFelder (sind eigentlich Panels) nicht mehr vorhanden sind
|
AW: generische ObjectList: Löschen eines Elementes
Zitat:
|
AW: generische ObjectList: Löschen eines Elementes
Zitat:
|
AW: generische ObjectList: Löschen eines Elementes
huch - da ist ein Problem! :-)
Mist - geändert - aber nie komplett getestet |
AW: generische ObjectList: Löschen eines Elementes
Zitat:
Delphi-Quellcode:
Aber auch bei generischen Listen kann man für sowas immernoch eine For-Do-Schleife benutzen.
procedure Masken_ausblenden(akt_MaskID: String);
var MaskeFeld: TMaskeFeld; begin for MaskeFeld in ObjectList_sichtbare_Masken.Reverse do If MaskeFeld.NameID <> akt_MaskID then begin MaskeFeld.Visible := False; ObjectList_sichtbare_Masken.Remove(MaskeFeld); end; end; Oder vielleicht auch so?
Delphi-Quellcode:
procedure Masken_ausblenden(akt_MaskID: String);
var MaskeFeld, MaskeFeld2: TMaskeFeld; begin MaskeFeld := ObjectList_sichtbare_Masken.Find(MaskID); // sowas ist das Erste, was man sich baut - womöglich mit passendem Comperator for MaskeFeld2 in ObjectList_sichtbare_Masken do MaskeFeld2.Visible := MaskeFeld2 = MaskeFeld; ObjectList_sichtbare_Masken.Clear; ObjectList_sichtbare_Masken.Add(MaskeFeld); end; |
AW: generische ObjectList: Löschen eines Elementes
Zitat:
daher ist es nicht so einfach ich bin jetzt einfach wieder auf die alte for-Schleife umgestiegen, aber halt in Verbindung mit Generics
Delphi-Quellcode:
procedure Masken_ausblenden(akt_MaskID: String);
var i : Integer; MaskeFeld: TMaskeFeld; begin for i := Pred(ObjectList_sichtbare_Masken.Count) downto 0 do begin MaskeFeld := ObjectList_sichtbare_Masken.Items[i]; If MaskeFeld.NameID <> akt_MaskID then begin MaskeFeld.Visible := false; ObjectList_sichtbare_Masken.Delete(i); end; end; end; |
AW: generische ObjectList: Löschen eines Elementes
Ich finde Iteratoren ja auch ganz elegant, aber wenn ich etwas mit der Liste anstellen muss (oder den Index brauche), dann nehe ich auch die gute alte for-Schleife. Einfach, klar, direkt und kein überflüssiger Firlefanz.
Mich wundert es, das Delphi erlaubt, während der Verwendung eines Iterators die Liste manipulieren zu dürfen. Das ist sehr unsauber. |
AW: generische ObjectList: Löschen eines Elementes
Und? Wenn der das nicht erlauben würde dann einfach so
Delphi-Quellcode:
;)
for LItem in MyList.ToArray do
MYList.Remove( LItem ); Nicht, das jemand meint das wäre jetzt schneller als über den Index, aber es geht halt :stupid: |
AW: generische ObjectList: Löschen eines Elementes
Mit ToArray mache ich das auch meistens, ja. Der Geschwindigkeitsunterschied ist in den meisten Fällen vernachlässigbar und so ist es einfach schöner lesbar.
|
AW: generische ObjectList: Löschen eines Elementes
Hmm.. Wenn "MyList" noch keinen Zugriff über einen Index hätte (wie bei einem Dataset z.B.), würde ich das auch so machen, aber so... Ist das irgendwie ein ziemlich überflüssiger Schritt.
Aber klar: Wieso einfach, wenns auch umständlich geht. |
AW: generische ObjectList: Löschen eines Elementes
Zitat:
|
AW: generische ObjectList: Löschen eines Elementes
Ein FailFast wäre schon was feines im 'Remove', wenn ein Iterator gerade aktiv ist. Scheint aber keine Sau zu stören. Insofern ist Delphi hier näher an C dran, als an C#. Blöd.
|
AW: generische ObjectList: Löschen eines Elementes
Die Borland Standard-Collections kann man sich sowieso abgewöhnen- Die Collections aus Spring4D wrappen (ich glaube allesamt) zwar die Standard-Collections, aber haben auch daran gedacht: Wenn der Iterator eins weiter wandert und sich die Collection geändert hat fliegt man raus. 8-)
(Nicht das Entfernen aus der Collection)- Bekommt das noch deinen Segen? |
AW: generische ObjectList: Löschen eines Elementes
Zitat:
Was mir in Verbindung mit der Frage noch einfiel ist, dass ich mal in IList<T> ein ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:10 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