Ich verwende eine for-Schleife oder eine foreach-Schleife (spielt keine Rolle), um alle meine Objekte zu durchlaufen, wenn sie aktualisiert oder gezeichnet werden müssen. Wenn ein Objekt jedoch getötet wird, möchte ich, dass es wieder aus der Sammlung entfernt wird.
Dazu füge ich das Objekt einer Liste mit toten Objekten hinzu. Wenn dann alles gezeichnet und aktualisiert wurde, gehe ich alles in dieser Liste durch und entferne auch die Objekte in der Liste aus der Originalquelle.
Gibt es einen besseren Weg, dies zu tun?
Antworten:
Zuallererst: Terminologie. Wenn Sie "Müllliste" sagen, denken die Leute, Sie sprechen über den Müllsammler. Nennen wir es die "tote Liste".
Wie Sie wahrscheinlich festgestellt haben, können Sie daher bei Ihrer Frage keine Elemente aus einer Sammlung entfernen, während Sie diese durchlaufen. Wenn es sich bei Ihrer Sammlung um eine handelt
List<>
, können Sie Elemente am einfachsten entfernen:Beachten Sie, dass Sie rückwärts iterieren . Sie können Elemente entfernen, während Sie vorwärts iterieren, aber es ist unordentlicher und erfordert a
goto
. Sie können es nicht mit tunforeach
.Sie können das Entfernen entweder separat von Ihrer Aktualisierungsschleife durchführen. Oder Sie können es in Ihre Update-Schleife einfügen. Führen Sie dies immer
RemoveAt
am Ende der Schleife durch - nach diesem Punkt in der Schleifelist[i]
kann dies nicht als gültig angesehen werden (es wird bei der nächsten Iteration wieder gültig).Beachten Sie auch, dass jedes Objekt ein eigenes
IsDead
Flag hat (wenn Sie das Entsorgungsmuster verwenden, können Sie es erstellenIsDisposed
) - Sie müssen überhaupt keine "tote Liste" führen.Die Verwendung eines Flags für jedes Element ist für die Leistung vorzuziehen, da Sie nicht die Liste durchsuchen müssen, um das Entfernen durchzuführen. Und es ist auch für das Design vorzuziehen - es bedeutet, dass jedes Objekt leicht überprüfen kann, ob es tot ist - damit Sie nicht versehentlich Methoden darauf aufrufen (wenn diese Objekte das Einwegmuster implementieren, können sie
ObjectDisposedException
in diesem Fall werfen ).Wenn Sie eine andere Sammlung als a haben
List<>
, muss beim Entfernen toter Elemente aus dieser Sammlung möglicherweise noch eine tote Liste erstellt werden (da das Entfernen während der Iteration möglicherweise nicht möglich ist). Meiner Meinung nach ist es in Bezug auf das DesignIsDead
besser , die Dead List direkt vor ihrer Verwendung zu erstellen, indem Sie die Sammlung nach Flags durchsuchen, anstatt zu versuchen, die Liste beizubehalten, wenn Objekte getötet werden.Sobald Sie mit einer toten Liste fertig sind, sollten Sie
Clear()
sie aufbewahren und dann aufbewahren, um sie später wiederzuverwenden.quelle
IsDead
Muster ist funktional identisch mitIsDisposed
. Die semantische VerwendungIsDead
bedeutet, dass Sie eine Liste zum Zeichnen / Aktualisieren dieser Objekte verwalten, aus der zu einem späteren Zeitpunkt tote Elemente entfernt werden. Das Entsorgungsmuster impliziert dies nicht. Darüber hinaus ist die Entsorgung Muster nicht bedeuten , dass Sie von diesem Objekt gehalten verwalteten Ressourcen haben (was für Gameplay - Objekte in der Regel nicht geeignet ist).In 99,9% der Fälle kümmert sich der Garbage Collector (GC) problemlos um alles. Lassen Sie es einfach seine Arbeit machen, sobald Sie diese Objekte gelöscht / auf Null gesetzt haben. Es gibt eine Latenz bei der Bereinigung, die von einer Reihe von Faktoren abhängt (wie viele Speicherblöcke beispielsweise zugewiesen wurden), aber Sie müssen normalerweise nicht einmal darüber Bescheid wissen, geschweige denn darüber nachdenken. Es ist so konzipiert, dass es nur funktioniert. Welches ist ein Grund, warum Sie C # und nicht C verwenden.
Bezüglich der GC-Leistung im Allgemeinen sollten Sie sich nicht übermäßig Sorgen machen, es sei denn, Sie wissen (durch Profilerstellung), dass dies zu einem Engpass führt - dies ist im Allgemeinen nur bei recht anspruchsvollen Spielen der Fall. Wenn dies der Fall ist, schauen Sie sich GC.Collect () und seine verschiedenen Fallstricke an, damit Sie wissen, wann es angemessen ist, es zu verwenden. Ich schlage vor, "force gc xna" zu googeln, da draußen gibt es viel Material.
quelle