Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!
Werbeanzeige
Zitat von »Schorsch«
Deine zweite Variante wird in den meisten Fällen wohl nicht so gut sein. Es sei denn 0 wäre in dem Fall kein valider Wert in deiner Collection. Am besten man wirft hier einfach eine Exception. Damit ist man immer auf der sicheren Seite. Auch wenn sich der Wertebereich der Collection ändert. Auch wenn das hier sicherlich nur ein Beispiel von dir war.
Ich gebe in solchen Fällen gerne eine Iterator Range zurück. Also so etwas in der Art:
template <typename Iterator>
class Range {
public:
Range(Iterator begin, Iterator end);
auto begin() const -> Iterator;
auto end() const -> Iterator;
private:
Iterator m_begin, m_end;
};
Das lässt sich bei Bedarf dann auch prima in range-based for Loops benutzen.
Ich habe aber auch schon mit der Möglichkeit geliebäugelt, foreach-Methoden für das Iterieren über private Container anzubieten:
C-/C++-Quelltext
class World {
public:
void forEachTown(std::function<void(Town&)>);
void forEachVillage(std::function<void(Village&)>);
}
Beide Methoden könnten hier auf demselben Container operieren, ihn aber unterschiedlich filtern. Allerdings habe ich so etwas bisher noch nicht benötigt.
Zitat von »dot«
Ich frag mich in solchen Fällen immer erst einmal, wieso genau die Collection im Interface exposed werden sollte, denn meistens ist so eine Collection meiner Erfahrung nach eher ein Implementierungsdetail, welches besser nicht nach draußen geht. Anstatt den internen vector weiterzureichen, damit andere drüber iterieren können, sollte nicht besser das Iterieren etc. Methode des Besitzers der Collection sein?
Zitat von »dot«
IEnumerable tut ebenfalls nichts Anderes, als die Tatsache, dass es unter der Haube eine Collection gibt, nach außen zu tragen. Außerdem ist es nicht effizient...
Zitat von »dot«
Ich frag mich in solchen Fällen immer erst einmal, wieso genau die Collection im Interface exposed werden sollte, denn meistens ist so eine Collection meiner Erfahrung nach eher ein Implementierungsdetail, welches besser nicht nach draußen geht. Anstatt den internen vector weiterzureichen, damit andere drüber iterieren können, sollte nicht besser das Iterieren etc. Methode des Besitzers der Collection sein?
Auf die Frage hab ich von dir schon gewartet . Ganz einfach: Es gibt ein Objekt, welches Objekte besitzt und einem anderen Objekt bereitstellen soll, um sie zu verarbeiten, weil die Verarbeitung gar nichts mit dem Besitzer der Objekte in der Collection zu tun hat und vor allem die Verarbeitung prinzipiell erstmal in einem Interface abgebildet ist [...]
Zitat von »dot«
IEnumerable tut ebenfalls nichts Anderes, als die Tatsache, dass es unter der Haube eine Collection gibt, nach außen zu tragen. Außerdem ist es nicht effizient...
Das stimmt so direkt nicht. IEnumerable hat nichts Listen oder dergleichen zu tun sondern definiert nur ähnlich wie ein Iterator, dass man von einem Element zum nächsten kommt und irgendwann Schluss ist. Und das ist doch eine sehr gute Schnittstelle.
Und dass IEnumerable<> prinzipiell langsam ist ist quatsch, oftmals ist sogar schneller, weil IEnumerables lazy arbeiten. Somit besteht die potenzielle Chance, dass die Menge an zu verarbeitenden Objekten mit jedem Weiterverarbeiten kleiner wird und somit einiges an Zeit gespart wird. Besonders gut merkt man das an Linq-Ausdrücken, die sehr elegant und einfach zu bedienen sind und trotzdem ziemlich fix sind. Und der Vergleich mit C++ bzgl. Performance ist sowieso immer so eine Sache mein Bester
Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »dot« (26.02.2014, 10:59)
Community-Fossil
Zitat von »dot«
Deine Antwort ist also: "Es muss so sein, weil es so sein muss."!?
Wieso besitzt dieses Objekt weitere Objekte, die dann aber von anderen Objekten verarbeitet werden? Was sind das für andere Objekte und von welcher Art von "Verarbeitung" reden wir hier? Wieso besitzt ersteres Objekt überhaupt Objekte, mit denen es nichts zu tun hat?
Zitat von »dot«
Wenn du mich fragst, ist das in den wenigsten Fällen eine gute Schnittstelle (siehe oben).
Wie du richtig erkannt hast, repräsentiert IEnumerable effektiv nichts anderes als eine sequentielle Collection die forward Iteration unterstützt. Indem du IEnumerable<T> implementierst, drückst du aus: "Das hier ist eine sequentielle Collection, durch die von hinten nach vorne iteriert werden kann."
Zitat von »dot«
Ich versuche hier nicht, C# und C++ zu vergleichen. Ich dachte, deine Frage war, wie man gewisse Dinge in C++ lösen würde!? Meine Kritik richtet sich nicht gegen C#, sondern dagegen, den C# Ansatz 1:1 auf C++ zu übertragen. Ineffizient ist das insofern, als jeder Iterationsschritt über virtual Function Calls abgewickelt wird. Im Vergleich zu z.B. einer generischen Lösung wie std::vector, ist das sogar lächerlich ineffizient, so lange nicht die in jedem Iterationsschritt stattfindende Verarbeitung vergleichsweise teuer ist...
Community-Fossil
Zitat von »TrommlBomml«
Damit hat man doch die möglichkeit, den Zugriff nach außen zu beschränken. Du kannst, wenn du eine IEnumerable herausgibst, die Original-Collection nicht verändern, sondern nur lesen und iterieren - das ist doch Klasse! In C++ hält dich bei der Herausgabe eines vektors keiner davon ab, delete aufzurufen.
Zitat von »TrommlBomml«
Das finde ich sehr schade.
Zitat von »TrommlBomml«
Dafür kann man "nur" Iteratoren herausreichen, find ich personlich aber auch alles andere als schön
Zitat von »TrommlBomml«
Versichern tut dir das keiner, aber es scheitert Performance ja nicht in der Regel am durchiterieren einer Liste
Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Spiele Programmierer« (26.02.2014, 14:55)
Zitat von »TrommlBomml«
Damit hat man doch die möglichkeit, den Zugriff nach außen zu beschränken. Du kannst, wenn du eine IEnumerable herausgibst, die Original-Collection nicht verändern, sondern nur lesen und iterieren - das ist doch Klasse! In C++ hält dich bei der Herausgabe eines vektors keiner davon ab, delete aufzurufen.
Das geht doch bei C++ auch... ?
Einfach einen (konstanten) Iterator nehmen oder direkt ("const std::vector<...>") . Wo gibt es da bei C++ konkret einen Nachteil?
Zitat von »Spiele Programmierer«
das in C# kein vereinheitlichtes Interface zb. für bidirektionale Iteratoren oder Random Access existiert. Geschweige denn ein Äquivalent für das C++ "const" oder gar reverse Iteratoren.
Zitat von »Spiele Programmierer«
Die Frage ist eher, warum hier Performance verschenken wenn es auch ohne ginge. Und zwei virtual Calls bei jeder Iteratoren ist schon relativ heftig.
Werbeanzeige