Цикл foreach якобы создает объект IEnumerator из коллекции, которую вы передаете, и затем просматривает ее. Итак, такой цикл:
foreach(var entry in collection)
{
entry.doThing();
}
переводит что-то вроде этого:
(исключая некоторые сложности в отношении того, как перечислитель будет позже)
var enumerator = collection.GetEnumerator();
while(enumerator.MoveNext()) {
var entry = enumerator.Current;
entry.doThing();
}
Если это скомпилировано наивно / напрямую, то этот объект перечислителя размещается в куче (что занимает немного времени), даже если его базовый тип является структурой, называемой боксом. После завершения цикла это распределение становится мусором для последующей очистки, и ваша игра может на мгновение заикаться, если накапливается достаточно мусора, чтобы сборщик мог выполнить полную очистку. Наконец, MoveNext
метод и Current
свойство могут включать больше шагов вызова функции, чем просто захват элемента напрямую collection[i]
, если компилятор не встроит это действие.
Приведенные выше ссылки на документацию по Unity в Hellium указывают на то, что эта наивная форма - это именно то, что происходит в Unity до версии 5.5 , если выполнять итерации по чему-либо, кроме собственного массива.
В версии 5.6+ (включая версии 2017 года) этот ненужный бокс исчез , и вы не должны испытывать ненужного выделения, если используете какой-либо конкретный тип (например, int[]
или List<GameObject>
или Queue<T>
).
Вы все равно получите распределение, если рассматриваемый метод знает только, что он работает с каким-то IList или другим интерфейсом - в этих случаях он не знает, с каким конкретным перечислителем он работает, поэтому он должен сначала поместить его в объект IEnumerator. ,
Так что есть хороший шанс, что это старый совет, который не так важен в современном развитии Unity. Единство УБС , как мы можем быть немного суеверны о вещах , которые используются , чтобы быть медленными / волосатой в старых версиях, поэтому принимать какую - либо рекомендацию этой формы с зерном соли. ;) Двигатель развивается быстрее, чем наши убеждения по этому поводу.
На практике у меня никогда не было игр, демонстрирующих заметную медлительность или сбой при сборке мусора при использовании циклов foreach, но ваш пробег может варьироваться. Профилируйте свою игру на выбранном оборудовании, чтобы увидеть, стоит ли беспокоиться об этом. Если вам нужно, довольно просто заменить циклы foreach явными циклами for на более поздних этапах разработки в случае возникновения проблемы, поэтому я бы не стал жертвовать удобочитаемостью и простотой кодирования на ранних этапах разработки.