Когда вы делаете такие вещи, как:
for (int i = 0; i < collection.Count; ++i )
вызывается collection.Count на каждой итерации?
Изменится ли результат, если свойство Count будет динамически получать количество вызовов?
Вопрос
Когда вы делаете такие вещи, как:
for (int i = 0; i < collection.Count; ++i )
вызывается collection.Count на каждой итерации?
Изменится ли результат, если свойство Count будет динамически получать количество вызовов?
Да Количество будет оцениваться при каждом проходе. Причина в том, что коллекция может быть изменена во время выполнения цикла. Учитывая структуру цикла, переменная i должна представлять действительный индекс в коллекции во время итерации. Если проверка не выполнялась в каждом цикле, то это недоказуемо. Пример случая
for ( int i = 0; i < collection.Count; i++ ) {
collection.Clear();
}
Единственным исключением из этого правила является цикл по массиву, где ограничением является длина.
for ( int i = 0; i < someArray.Length; i++ ) {
// Code
}
CLR JIT будет использовать этот тип цикла в особых случаях, поскольку длина массива не может измениться. В этих случаях проверка границ будет происходить только один раз.
Ссылка: http://blogs.msdn.com/brada/archive/2005/04/23/411321.aspx
Количество будет оцениваться при каждом проходе. Если бы вы продолжали добавлять в коллекцию, а итератор так и не догнал, у вас был бы бесконечный цикл.
class Program
{
static void Main(string[] args)
{
List<int> intCollection = new List<int>();
for(int i=-1;i < intCollection.Count;i++)
{
intCollection.Add(i + 1);
}
}
}
Это в конечном итоге приведет к исключению нехватки памяти.
Да счетчик проверяется при каждом вызове от первой итерации после инициализации i до последней итерации, где проверка не удалась и цикл for вышел. Вы можете изменить количество коллекций, если хотите, но понимаете, что можете попасть в бесконечный цикл.
Как и другие ответы здесь: Да, в принципе.
Существует (по крайней мере) одно заметное исключение, array.Length. В
for (int i = 0; i < a.Length; i++) a[i] = ...;
Свойство Length будет оцениваться только один раз. Это оптимизация, встроенная в компилятор. Могут быть и другие подобные (в будущем), но только если это гарантированно не будет иметь значения в наблюдаемом поведении.
Примечание: это НЕ проверяется для каждого взаимодействия в VB.
В отличие от C#, VB кэширует результат collection.Count.
РЕДАКТИРОВАТЬ:
Буквальная версия VB цикла C# for:
Dim i = 0
Do While i < collection.Count
'code goes here
i+=1
Loop
Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.