Eine foreach-Schleife erstellt angeblich ein IEnumerator-Objekt aus der Sammlung, die Sie übergeben, und geht dann darüber hinweg. Also eine Schleife wie diese:
foreach(var entry in collection)
{
entry.doThing();
}
übersetzt sich in etwas wie
folgt : (einige Komplexität darüber, wie der Enumerator später entsorgt wird, entfällt)
var enumerator = collection.GetEnumerator();
while(enumerator.MoveNext()) {
var entry = enumerator.Current;
entry.doThing();
}
Wenn dies naiv / direkt kompiliert wird, wird dieses Enumerator-Objekt auf dem Heap zugewiesen (was etwas Zeit in Anspruch nimmt), selbst wenn sein zugrunde liegender Typ eine Struktur ist - etwas, das als Boxen bezeichnet wird. Nachdem die Schleife abgeschlossen ist, wird diese Zuordnung zu Müll, um sie später zu bereinigen, und Ihr Spiel kann für einen Moment stottern, wenn sich genug Müll ansammelt, damit der Sammler einen vollständigen Sweep ausführen kann. Schließlich können die MoveNext
Methode und die Current
Eigenschaft mehr Funktionsaufrufschritte umfassen, als nur ein Element direkt mit abzurufen collection[i]
, wenn der Compiler diese Aktion nicht einbindet.
Die Hellium-Links zu Unity-Dokumenten oben zeigen an, dass diese naive Form genau das ist, was in Unity vor Version 5.5 passiert , wenn über etwas anderes als ein natives Array iteriert wird.
In Version 5.6+ (einschließlich 2017-Versionen) ist dieses unnötige Boxen weg , und Sie sollten keine unnötige Zuordnung erfahren, wenn Sie einen konkreten Typ verwenden (z. B. int[]
oder List<GameObject>
oder Queue<T>
).
Sie erhalten weiterhin eine Zuordnung, wenn die betreffende Methode nur weiß, dass sie mit einer Art IList oder einer anderen Schnittstelle funktioniert. In diesen Fällen weiß sie nicht, mit welchem bestimmten Enumerator sie arbeitet, sodass sie zuerst in ein IEnumerator-Objekt gepackt werden muss .
Es besteht also eine gute Chance, dass dies ein alter Rat ist, der in der modernen Unity-Entwicklung nicht so wichtig ist. Unity-Entwickler wie wir können ein bisschen abergläubisch gegenüber Dingen sein, die in alten Versionen langsam / haarig waren. Nehmen Sie also jeden Rat dieser Form mit einem Körnchen Salz. ;) Der Motor entwickelt sich schneller als wir glauben.
In der Praxis hatte ich noch nie ein Spiel, das durch die Verwendung von foreach-Schleifen merkliche Langsamkeit oder Probleme mit der Speicherbereinigung aufwies, aber Ihr Kilometerstand kann variieren. Profilieren Sie Ihr Spiel auf der von Ihnen gewählten Hardware, um festzustellen, ob es sich überhaupt lohnt, sich Sorgen zu machen. Wenn Sie müssen, ist es ziemlich trivial, foreach-Schleifen später in der Entwicklung durch explizite for-Schleifen zu ersetzen, falls sich ein Problem manifestiert, damit ich nicht zu Beginn der Entwicklung auf Lesbarkeit und einfache Codierung verzichten würde.