for 루프 또는 foreach 루프를 사용하여 업데이트하거나 그려야 할 때 모든 객체를 반복합니다. 그러나 객체가 죽으면 컬렉션에서 다시 제거하고 싶습니다.
죽은 개체 목록에 개체를 추가하여이 작업을 수행 한 다음 모든 것이 그려지고 업데이트되면이 목록의 모든 항목을 검토하여 목록의 개체를 원래 소스에서도 제거합니다.
더 좋은 방법이 있습니까?
for 루프 또는 foreach 루프를 사용하여 업데이트하거나 그려야 할 때 모든 객체를 반복합니다. 그러나 객체가 죽으면 컬렉션에서 다시 제거하고 싶습니다.
죽은 개체 목록에 개체를 추가하여이 작업을 수행 한 다음 모든 것이 그려지고 업데이트되면이 목록의 모든 항목을 검토하여 목록의 개체를 원래 소스에서도 제거합니다.
더 좋은 방법이 있습니까?
답변:
우선 : 용어. "가비지 목록"이라고 말하면 사람들은 가비지 수집기에 대해 이야기하고 있다고 생각할 것입니다. 이것을 "데드리스트"라고하자.
당신이 아마 발견했듯이, 질문은, 당신이 그것을 반복하는 동안 컬렉션에서 아이템을 제거 할 수 없습니다. 컬렉션이 List<>
아이템을 제거하는 가장 간단한 방법 인 경우 :
for(int i = list.Count-1; i >= 0; --i)
{
if(list[i].IsDead)
list.RemoveAt(i);
}
거꾸로 반복한다는 점에 유의하십시오 . 앞으로 반복하면서 항목을 제거 할 수 있지만 더 복잡하고가 필요합니다 goto
. 로 할 수 없습니다 foreach
.
업데이트 루프와 별도로 제거를 수행 할 수 있습니다. 또는 업데이트 루프에 병합 할 수 있습니다. 항상 RemoveAt
루프 끝에서를 수행하십시오 . 루프의 해당 지점 이후에는 list[i]
유효한 것으로 간주 할 수 없습니다 (다음 반복에서 다시 유효하게 됨).
또한 각 객체에는 고유 한 IsDead
플래그가 있습니다 (처분 패턴을 사용하는 경우이를 만들 수 있음 IsDisposed
). 실제로 "데드 목록"을 유지할 필요는 없습니다.
제거를 위해 목록을 검색하지 않아도되므로 성능을 위해 각 항목에 플래그를 사용하는 것이 좋습니다. 또한 디자인에 바람직합니다. 즉, 각 객체가 죽은 지 쉽게 확인할 수 있음을 의미하므로 실수로 객체에 대한 메소드를 호출하지 않습니다 (이러한 객체가 일회용 패턴을 구현하는 ObjectDisposedException
경우이 경우에 발생할 수 있음).
가 아닌 컬렉션이있는 경우 List<>
해당 컬렉션에서 죽은 항목을 제거하면 여전히 죽은 목록이 생성 될 수 있습니다 (반복 중 제거가 불가능할 수 있음). 제 생각에는 IsDead
개체가 죽을 때 목록을 유지하려고하는 대신 플래그를 찾는 컬렉션을 반복하여 사용하기 전에 죽은 목록을 만드는 것이 더 좋습니다 .
사용 불능 목록으로 완료되면 Clear()
나중에 다시 사용할 수 있도록 보관 해야 합니다.
IsDead
패턴은 기능적으로 동일 IsDisposed
. 의미 적으로 사용 IsDead
한다는 것은 나중에 죽은 항목이 제거 될 이러한 객체의 그리기 / 업데이트 목록을 유지하고 있음을 의미합니다. 폐기 패턴이이를 의미하지는 않습니다. 또한 처리 패턴 은 해당 개체가 관리 하지 않는 리소스를 보유하고 있음을 의미합니다 (일반적으로 게임 플레이 개체에는 적합하지 않음).
99.9 %의 시간 동안 가비지 수집기 (GC)는 번거 로움없이 모든 것을 처리합니다. 해당 객체를 삭제하거나 null로 설정하면 작동하게하십시오. 정리에는 대기 시간이 여러 가지 요소 (예 : 할당 된 메모리 블록 수)에 따라 달라 지지만 걱정할 필요는 없지만 일반적으로 그것에 대해 알 필요는 없습니다. 그것은 단지 작동하도록 설계되었습니다. 이것이 C가 아닌 C #을 사용하는 이유 중 하나입니다.
일반적으로 GC 성능은 병목 현상이 발생한다는 것을 프로파일 링을 통해 알지 않는 한 지나치게 걱정하지 마십시오. 일반적으로 매우 까다로운 게임에서만 발생합니다. 이 경우 GC.Collect () 및 다양한 함정을 살펴보면 언제 사용해야하는지 알 수 있습니다. 인터넷 검색 "force gc xna"를 제안합니다. 많은 자료가 있습니다.