Loop foreach seolah-olah menciptakan objek IEnumerator dari koleksi yang Anda lewati, dan kemudian berjalan di atasnya. Jadi satu loop seperti ini:
foreach(var entry in collection)
{
entry.doThing();
}
diterjemahkan menjadi sesuatu yang sedikit seperti ini:
(menghilangkan beberapa kerumitan tentang bagaimana enumerator dibuang nanti)
var enumerator = collection.GetEnumerator();
while(enumerator.MoveNext()) {
var entry = enumerator.Current;
entry.doThing();
}
Jika ini dikompilasi secara naif / langsung, maka objek enumerator itu akan dialokasikan pada heap (yang membutuhkan sedikit waktu), bahkan jika tipe dasarnya adalah struct - sesuatu yang disebut tinju. Setelah pengulangan selesai, alokasi ini menjadi sampah untuk dibersihkan nanti, dan permainan Anda dapat gagap sesaat jika cukup banyak sampah yang menumpuk bagi kolektor untuk menjalankan sapuan penuh. Terakhir, MoveNext
metode dan Current
properti bisa melibatkan lebih banyak langkah-langkah pemanggilan fungsi daripada hanya mengambil item secara langsung collection[i]
, jika kompiler tidak sejalan dengan tindakan itu.
Unity docs tautan Hellium di atas menunjukkan bahwa bentuk naif ini adalah persis apa yang terjadi di Unity sebelum versi 5.5 , jika mengulangi apa pun selain dari Array asli.
Dalam versi 5.6+ (termasuk versi 2017), tinju yang tidak perlu ini hilang , dan Anda seharusnya tidak mengalami alokasi yang tidak perlu jika Anda menggunakan jenis beton apa pun (mis. int[]
Atau List<GameObject>
atau Queue<T>
).
Anda masih akan mendapatkan alokasi jika metode yang dimaksud hanya tahu bahwa itu bekerja dengan semacam IList atau antarmuka lainnya - dalam kasus itu tidak tahu enumerator spesifik apa yang bekerja dengannya sehingga harus mengotakkannya menjadi objek IEnumerator terlebih dahulu .
Jadi, ada kemungkinan bagus ini saran lama yang tidak begitu penting dalam pengembangan Persatuan modern. Persatuan devs seperti kita bisa sedikit percaya pada hal-hal yang dulu lambat / berbulu dalam versi lama, jadi ikuti saran dari bentuk itu dengan sebutir garam. ;) Mesin berkembang lebih cepat daripada keyakinan kami tentang hal itu.
Dalam praktiknya, saya tidak pernah memiliki permainan yang menunjukkan kelambatan yang terlihat atau cegukan pengumpulan sampah karena menggunakan foreach loop, tetapi jarak tempuh Anda mungkin berbeda. Profil game Anda pada perangkat keras yang Anda pilih untuk melihat apakah itu layak untuk dikhawatirkan. Jika Anda perlu, itu cukup sepele untuk mengganti foreach loop dengan eksplisit untuk loop nanti dalam pengembangan harus manifes masalah, jadi saya tidak akan mengorbankan keterbacaan dan kemudahan pengkodean awal pengembangan.