Saya menggunakan for for atau foreach loop (tidak masalah) untuk mengulangi semua objek saya ketika mereka perlu diperbarui atau digambar. Namun, ketika sebuah objek terbunuh, saya ingin itu dihapus dari koleksi lagi.
Saya melakukan ini dengan menambahkan objek ke daftar objek mati, dan kemudian, ketika semuanya telah ditarik dan diperbarui, saya memeriksa semua yang ada di daftar ini, menghapus objek dalam daftar dari sumber aslinya juga.
Apakah ada cara yang lebih baik untuk melakukan ini?
Jawaban:
Pertama-tama: terminologi. Jika Anda mengatakan "daftar sampah", orang akan berpikir Anda berbicara tentang pengumpul sampah. Sebut saja "daftar mati".
Seperti yang mungkin telah Anda temukan, maka pertanyaan Anda, Anda tidak dapat menghapus item dari koleksi saat Anda mengulanginya. Jika koleksi Anda adalah
List<>
maka cara paling sederhana untuk menghapus item dari itu adalah:Perhatikan bahwa Anda mengulangi mundur . Anda dapat menghapus item saat iterasi ke depan, tetapi lebih berantakan dan membutuhkan
goto
. Anda tidak dapat melakukannya denganforeach
.Anda dapat melakukan penghapusan secara terpisah dari loop pembaruan Anda. Atau Anda dapat menggabungkannya ke dalam loop pembaruan Anda. Selalu lakukan
RemoveAt
pada akhir loop - setelah titik itu dalam loop,list[i]
tidak dapat dianggap valid (itu menjadi valid lagi pada iterasi berikutnya).Perhatikan, juga, bahwa setiap objek memiliki
IsDead
benderanya sendiri (jika Anda menggunakan pola pembuangan, Anda dapat membuatnyaIsDisposed
) - Anda sebenarnya tidak perlu mempertahankan "daftar mati" sama sekali.Menggunakan bendera pada setiap item lebih disukai untuk kinerja, karena Anda menghindari harus mencari melalui daftar untuk melakukan penghapusan. Dan itu juga lebih baik untuk desain - itu berarti bahwa setiap objek dapat dengan mudah memeriksa apakah sudah mati - sehingga Anda tidak sengaja memanggil metode apa pun di atasnya (jika objek ini menerapkan pola sekali pakai, mereka dapat membuang
ObjectDisposedException
dalam kasus ini).Jika Anda memiliki koleksi selain a
List<>
, maka menghapus item yang mati dari koleksi itu mungkin masih melibatkan pembuatan daftar mati (karena penghapusan selama iterasi mungkin tidak mungkin). Menurut pendapat saya, lebih baik, lebih bijaksana secara desain, untuk membuat daftar mati tepat sebelum digunakan, dengan mengulangi koleksi yang mencariIsDead
bendera, daripada mencoba mempertahankan daftar ketika benda terbunuh.Setelah Anda selesai dengan daftar yang mati, Anda harus
Clear()
melakukannya, dan menyimpannya untuk menggunakannya kembali nanti.sumber
IsDead
Pola adalah fungsional identik denganIsDisposed
. Secara semantik menggunakanIsDead
menyiratkan bahwa Anda mempertahankan daftar Draw / Update objek-objek ini yang akan menghapus item mati dari itu di lain waktu. Pola pembuangan tidak menyiratkan hal itu. Selain itu, pola pembuangan tidak menyiratkan bahwa Anda mungkin memiliki sumber daya yang tidak dikelola yang dipegang oleh objek tersebut (yang biasanya tidak sesuai untuk objek gameplay).99,9% dari waktu, pengumpul sampah (GC) akan mengurus semuanya tanpa kerepotan. Biarkan saja fungsinya setelah Anda menghapus / membatalkan objek-objek itu. Ada latensi dalam pembersihan yang tergantung pada sejumlah faktor (berapa banyak blok memori yang telah ditetapkan misalnya) tetapi Anda tidak perlu biasanya tahu tentang itu, apalagi khawatir tentang hal itu. Ini dirancang hanya untuk bekerja. Yang merupakan salah satu alasan Anda menggunakan C # dan bukan C.
Re kinerja GC secara umum, jangan terlalu mengkhawatirkan diri sendiri kecuali jika Anda tahu (melalui profil) bahwa hal itu menciptakan kemacetan - ini hanya dalam permainan yang cukup menuntut, pada umumnya. Jika demikian, lihat GC.Collect (), dan berbagai perangkapnya, sehingga Anda tahu kapan waktu yang tepat untuk menggunakannya. Saya sarankan googling "force gc xna", ada banyak materi di luar sana.
sumber