Estoy usando un bucle for o foreach (no importa) para recorrer todos mis objetos cuando necesitan ser actualizados o dibujados. Sin embargo, cuando se mata un objeto, quiero que se elimine de la colección nuevamente.
Hago esto agregando el objeto a una lista de objetos muertos, y luego, cuando todo se ha dibujado y actualizado, reviso todo en esta lista, eliminando también los objetos de la lista de la fuente original.
¿Hay una mejor manera de hacer esto?
Respuestas:
En primer lugar: terminología. Si dices "lista de basura", la gente pensará que estás hablando del recolector de basura. Llamémosle la "lista muerta".
Como probablemente haya descubierto, de ahí su pregunta, no puede eliminar elementos de una colección mientras está iterando a través de ella. Si su colección es una,
List<>
entonces la forma más sencilla de eliminar elementos es:Tenga en cuenta que itera hacia atrás . Puede eliminar elementos mientras itera hacia adelante, pero es más complicado y requiere a
goto
. No puedes hacerlo conforeach
.Puede realizar la eliminación por separado de su ciclo de actualización. O puede fusionarlo en su ciclo de actualización. Siempre haga lo siguiente
RemoveAt
al final del ciclo; después de ese punto en el ciclo,list[i]
no puede considerarse válido (vuelve a ser válido en la próxima iteración).Tenga en cuenta, además, que cada objeto tiene su propia
IsDead
bandera (si está utilizando el patrón de eliminación, podría hacerloIsDisposed
): en realidad no necesita mantener una "lista muerta".Es preferible usar una bandera en cada elemento para el rendimiento, ya que evita tener que buscar en la lista para realizar la eliminación. Y también es preferible para el diseño, significa que cada objeto puede verificar fácilmente si está muerto, por lo que no llama accidentalmente a ningún método (si estos objetos están implementando el patrón desechable, podrían arrojarse
ObjectDisposedException
en este caso).Si tiene una colección distinta de a
List<>
, entonces eliminar elementos muertos de esa colección aún puede implicar la creación de una lista muerta (ya que la eliminación durante la iteración puede no ser posible). En mi opinión, es mejor, en cuanto al diseño, crear la lista muerta justo antes de que se use, iterando sobre la colección buscandoIsDead
banderas, en lugar de tratar de mantener la lista a medida que se eliminan los objetos.Una vez que haya terminado con una lista muerta, debe
Clear()
hacerlo, y luego guardarla para reutilizarla más adelante.fuente
IsDead
patrón es funcionalmente idéntico aIsDisposed
. Usar semánticamenteIsDead
implica que mantendrá una lista de Draw / Update de estos objetos que tendrá elementos muertos eliminados en un momento posterior. El patrón de eliminación no implica eso. Por otra parte, el patrón de la disposición no implica que usted pueda tener recursos no administrados en poder de ese objeto (que por lo general no es apropiado para objetos de juego).El 99.9% de las veces, el recolector de basura (GC) se encargará de todo sin problemas. Simplemente deje que haga su trabajo una vez que haya eliminado / anulado esos objetos. Hay una latencia en la limpieza que depende de una serie de factores (cuántos bloques de memoria se han asignado, por ejemplo), pero normalmente no es necesario que lo sepas, y mucho menos que te preocupes. Está diseñado para funcionar solo. Cuál es una razón por la que estás usando C # y no C.
En cuanto al rendimiento de GC en general, no se preocupe demasiado a menos que sepa (a través de la creación de perfiles) que está creando un cuello de botella; esto es solo en juegos bastante exigentes, en general. Si este es el caso, mire GC.Collect () y sus diversas dificultades, para saber cuándo es apropiado usarlo. Sugiero buscar en Google "force gc xna", hay mucho material por ahí.
fuente