Une boucle foreach crée ostensiblement un objet IEnumerator à partir de la collection que vous lui avez passée, puis passe par-dessus. Donc, une boucle comme celle-ci:
foreach(var entry in collection)
{
entry.doThing();
}
se traduit par quelque chose comme ceci:
(éluder une certaine complexité autour de la façon dont l'énumérateur est éliminé plus tard)
var enumerator = collection.GetEnumerator();
while(enumerator.MoveNext()) {
var entry = enumerator.Current;
entry.doThing();
}
Si cela est compilé naïvement / directement, cet objet énumérateur est alloué sur le tas (ce qui prend un peu de temps), même si son type sous-jacent est un struct - quelque chose appelé boxe. Une fois la boucle terminée, cette allocation devient des ordures à nettoyer plus tard, et votre jeu peut bégayer pendant un moment si suffisamment de déchets s'empilent pour que le collecteur exécute un balayage complet. Enfin, la MoveNext
méthode et la Current
propriété peuvent impliquer plus d'étapes d'appel de fonction que de simplement saisir un élément directement avec collection[i]
, si le compilateur n'inline pas cette action.
Les liens Unity docs Hellium ci - dessus indiquent que cette forme naïve est exactement ce qui se passe dans Unity avant la version 5.5 , si elle itère sur autre chose qu'un tableau natif.
Dans la version 5.6+ (y compris les versions 2017), cette boxe inutile a disparu et vous ne devriez pas rencontrer d'allocation inutile si vous utilisez un type concret (par exemple, int[]
ou List<GameObject>
ou Queue<T>
).
Vous obtiendrez toujours une allocation si la méthode en question sait seulement qu'elle fonctionne avec une sorte d'IList ou une autre interface - dans ces cas, elle ne sait pas avec quel énumérateur spécifique elle travaille, elle doit donc la placer dans un objet IEnumerator en premier. .
Il y a donc de fortes chances que ce soit de vieux conseils qui ne sont pas si importants dans le développement moderne de Unity. L' unité devs comme nous pouvons être un peu superstitieux choses qui utilisé pour être poilu lent / dans les anciennes versions, afin de prendre des conseils de cette forme avec un grain de sel. ;) Le moteur évolue plus vite que nos croyances à ce sujet.
Dans la pratique, je n'ai jamais vu un jeu présenter une lenteur notable ou un hoquet de collecte de déchets à l'aide de boucles foreach, mais votre kilométrage peut varier. Profilez votre jeu sur le matériel que vous avez choisi pour voir si cela vaut la peine de s'inquiéter. Si vous en avez besoin, il est assez trivial de remplacer les boucles foreach par des boucles for explicites plus tard dans le développement si un problème se manifeste, donc je ne sacrifierais pas la lisibilité et la facilité de codage au début du développement.