![]() |
AW: For xx In xxx Schleife rückwärts?
Eben. In der Benutzung ist es aber exakt gleich. Heißt: Man müsste bei der Betrachtung stets nachschauen von was denn die Klasse, die in einem Quelltext benutzt wird, abgeleitet ist, um beurteilen zu können, ob ein Quelltext macht was er soll.
Und das ist ein No-Go in sauberem Quelltext. |
AW: For xx In xxx Schleife rückwärts?
Aber wie am Beispiel des TList.Reversed, kann man die Funktion auch direkt am Quellcode dokumentieren.
Also wenn man eine bestimmre Reihenfolge benötigt, dann kann man auch einen passenden Enumerator auch direkt angeben. Wie z.B. einen rückwärttslaufenden Enumerator, oder Einen, welcher die Liste vorher cached, wenn man innerhalb der Schleife die Liste verändern möchte, oder einen Enumerator, welcher die Liste gefilltert durchläuft und nur bestimmte Einträge behandelt. |
AW: For xx In xxx Schleife rückwärts?
Zitat:
Delphi-Quellcode:
Kein Parameter ohne Bedeutung: Das Objekt stellt einen Zusammenhang mit Daten her und die Klasse des Objekts stellt einen Zusammenhang mit Funktionen her. Stichwort: Polymorphie.
Objekt.Methode(Argument);
Methode(Objekt, Argument); Anderes Beispiel:
Delphi-Quellcode:
Ausgabe:
program Project1;
{$AppType Console} uses System.SysUtils, Spring.Collections, Spring.Collections.Lists, Spring.Collections.Sets; type T = String; procedure Enumerate(const Caption: String; const Enumerable: IEnumerable<T>); var Value: T; begin WriteLn(Caption); for Value in Enumerable do WriteLn(Value); end; procedure Run; var Collection1: IList<T>; Collection2: ISet<T>; Value: T; begin Collection1 := TList<T>.Create; Collection2 := THashSet<T>.Create; Collection1.Add('Eins.'); Collection1.Add('Eins.'); Collection1.Add('Zwei.'); Collection1.Add('Drei.'); Collection1.Add('Vier.'); Collection1.Add('Drei.'); for Value in Collection1 do Collection2.Add(Value); Enumerate('Aufzählung 1', Collection1); Enumerate('Aufzählung 2', Collection2); end; begin try Run; except on E: Exception do WriteLn(E.ClassName + ': ' + E.Message); end; if DebugHook <> 0 then ReadLn; end.
Code:
Das verdeutlicht vielleicht noch einmal auf andere Weise, dass das Objekt und seine Klasse bedeutsam sind für das, welche Funktion mit welchen Daten ausgeführt werden soll. Dieses Verhalten ist erwünscht und der wesentliche Grund dafür, warum wir Polymorphie nutzen. Bspw.
Aufzählung 1
Eins. Eins. Zwei. Drei. Vier. Drei. Aufzählung 2 Zwei. Drei. Eins. Vier.
Delphi-Quellcode:
ist für eine Liste eben anders definiert als für eine Menge. Gleichermaßen ist eine Aufzählung für eine Liste klar definiert, und kann durchaus von anderen Aufzählungen anderer Typen abweichen. Gleichsam sind beides Sammlungen und beide aufzählbar, was bei der Routine
Add
Delphi-Quellcode:
nützlich ist. Und eine Menge bietet eben keinen indizierten Zugriff auf ihre Elemente, der für eine For-to-Schleife benötigt wird. Er müsste erst künstlich geschaffen werden. Genauso bei dem
Enumerate
Delphi-Quellcode:
-Beispiel von oben;
TDictionary<...>
Delphi-Quellcode:
und
IDictionary<NativeInt, String>
Delphi-Quellcode:
sind eben unterschiedliche Typen, auch wenn beide einen
IList<TPair<NativeInt, String>>
Delphi-Quellcode:
anbieten.
IEnumerator<TPair<NativeInt, String>>
|
AW: For xx In xxx Schleife rückwärts?
Du bist ja ein richtiger Fachmann. :thumb: :lol:
Zitat:
Ein Enumerator hat genauso viel mit einer Liste zu tun wie ein Cursor mit einer Tabelle. Der Cursor zählt die Query auf, der Enumerator die Liste. Wo und wie ist denn die Reihenfolge definiert, wenn die nicht explizit festgelegt ist? Heute kommen die Daten so, morgen so. Glaubste nicht? Tja, dann fehlt dir was. Zitat:
Also nochmal, für Hausfrauen, zum Mitschreiben: Die Reihenfolge der Aufzählung ist implementierungsabhängig, mithin undefiniert (obwohl meistens deterministisch) und im Einzelfall durchaus heute anders als morgen. Sie darf auch nichtdeterministisch sein (RDBMS), d.h. jedesmal in einer anderen Reihenfolge. Der einzige Grund, weshalb das i.a. nicht der Fall ist, ist doch der, das es naheliegend ist, das ein Array oder eine Liste die Elemente mit einem Index aufzählt. Aber wie sieht es mit der Reihenfilge bei einer Hashmap aus? Oder einem Baum? Wie ist denn die Reihenfolge hier? Infix, Prefix, Postfix? Was ist mit einem ungerichteten Graphen? Trie? etc. etc. etc. Deshalb hat man doch gerade das gemeinsame IEnumerable-Paradigma, um die einzelnen Elemente wenigstens aufzählen zu können, auch Mengen ohne innere Ordnung. Mann, so schwer kann das doch nicht sein. |
AW: For xx In xxx Schleife rückwärts?
Code, bei dem ich erst die Klassenhierarchie studieren müsste um herauszufinden wie meine Schleife läuft (und dies relevant ist), würde ich dem Autor sowas von um die Ohren knallen, das glaubst du gar nicht. Das ist bewusstes torpedieren von Teamarbeit und Produktivität.
|
AW: For xx In xxx Schleife rückwärts?
Zitat:
Nun denn, wenn es darum geht Liste zu nennen, was keine ist, und Dinge nicht so zu implementieren, wie es ihr Name sagt, und man dabei Unsicherheit wider der Vernunft streut, während man beim Programmieren selbst immer wieder in die Defensive gerät - denn es könnte sich ja immer alles auch ein bisschen anders verhalten - dann sind wir beim Etikettenschwindel angekommen: Zitat:
|
AW: For xx In xxx Schleife rückwärts?
Im Grunde streitet ihr euch, ob ein foreach auf einem Iterator arbeitet (=> Reihenfolge hängt vom Iterator ab, kann je nach Art des Iterators bekannt oder unbekannt sein) oder auf einer Datenstruktur (=> Reihenfolge ist bei unbekannter Datenstruktur unbekannt, im Zweifelsfall Index benutzen). Mir ist die Iterator-Sichtweise lieber.
Was die Index-Fanatiker (SCNR) nicht berücksichtigen: Gerade der Zugriff durch den Index ist unter Umständen nicht wirklich effizient. Man denke nur mal an eine verkettete Liste: Der Index ist eigentlich überhaupt nicht interessant, man möchte nur einmal die Liste von vorne nach hinten durchlaufen. Trotzdem darf man jetzt Länge der Liste mal zu dem jeweils gesuchten Index laufen. Hurra, schon ist aus einer linearen eine quadratische Laufzeit geworden :thumb: Wenn ich einen bestimmten Iterator benutze/fordere, dann kann ich mich auf die Reihenfolge verlassen, die dieser garantiert. Die Anforderungen an den Iterator sollte man natürlich irgendwo dokumentieren :mrgreen: |
AW: For xx In xxx Schleife rückwärts?
Nettes Beispiel! Ich gebe zu, dass es hier tatsächlich ein Grenzfall ist. Und auch wenn ich bei verketteten Listen durchaus nicht die Nase rümpfen würde, wenn dort jemand "altbacken" mit einer while-Schleife und CurrentItem := CurrentItem.Next; durchrauscht, sehe ich eine potenzielle Vereinfachung durch for..in hier. In solch einem Fall würde ich mir dann aber schon einen explizit benutzten Iterator mit sinnvollem Namen wünschen, oder zumindest ein Wort dazu im Kommentar.
Delphi-Quellcode:
o.ä. Das würde sich wieder selbst dokumentieren wie der Index, ohne den von dir genannten Nachteil.
for Item in List.ForwardIterator do
|
AW: For xx In xxx Schleife rückwärts?
Zitat:
Was die Veränderung der durchlaufenden Struktur angeht ist die Implementierung in der Delphi RTL wirklich nicht sehr dolle. In Spring4d hingegen wird dir ein Enumerator mit einer Exception ins Gesicht springen, wenn du zwischendurch die zugrundelegende Datenmenge veränderst (analog zum Verhalten in .Net). Ich stimme den meisten hier zu, dass es gefährlich sein kann, anhand eines abstrakten Interfaces (IEnumerable<T>) auf ein Implementierungsdetail zu schließen. Deshalb würde ich in einem solchen Fall eher vorschlagen, ein weniger abstraktes zu benutzen. In Spring4d/.Net würde sich dort z.B. IList<T> anbieten. Dieses bietet direkten Indexzugriff und man kann sich sicher sein, dass implementierende Klassen den Enumerator auch in einer solchen Weise implementieren, dass die Liste von vorn nach hinten durchlaufen werden. Im übrigen macht das .Net Framework selber bei den diversen IEnumerable<T> extension methods implizite Annahmen über die Ausführung. Schaut euch einfach mal First, Last oder ElementAt an (welche intern eine Optimierung für den Fall haben, dass es sich um IList<T> handelt). Dass eine enumeration ein nicht erwartetes Ergebnis hat, habe ich erst kürzlich selbst erlebt, einfach mal eine PriorityQueue enumerieren und sich wundern, dass die Elemente eine andere Reihenfolge haben, als wenn man Dequeue aufruft, bis sie leer ist :) |
AW: For xx In xxx Schleife rückwärts?
Zitat:
Also falls die überhaupt einen Enumerator haben. Und wenn, müsste der Enumerator, bei sowas, nicht sogar der Liste geleert werden? (jedes Element müsse trausgenommen werden, sobaldes verarbeitet wird :gruebel:) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:51 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