Время от времени проблема была accuracy.txt
пустой, из-за чего цикл никогда не выполнялся и user_new
никогда не определялся. Спасибо @Joe Allen за ответ.
foreach создает экземпляр перечислителя (возвратился из GetEnumerator), и тот перечислитель также сохраняет состояние на всем протяжении цикла foreach. Это тогда неоднократно призывает к Следующему () объект на перечислителе и выполняет Ваш код для каждого объекта, который это возвращает.
Они не сводятся к тому же коду всегда, действительно, который Вы видели бы, записали ли Вы свой собственный перечислитель.
foreach образец примерно соответствует этому коду:
using(IEnumerator<Entity> e = entityList.GetEnumerator()) {
while(e.MoveNext()) {
Entity entity = e.Current;
...
}
}
существует два издержек здесь, которые не должен оплачивать постоянный клиент для цикла:
Одна суть упущена здесь: Список имеет свойство Count, он внутренне отслеживает то, сколько элементов находится в нем.
IEnumerable НЕ ДЕЛАЕТ.
, Если Вы программируете к интерфейсу IEnumerable и используете метод расширения количества, он перечислит только для подсчета элементов.
спорный вопрос А, хотя с тех пор в IEnumerable Вы не можете обратиться к объектам индексом.
Поэтому, если Вы хотите привязаться к Спискам и Массивам, можно получить маленькие увеличения производительности.
, Если Вы хотите использование гибкости foreach и программу к IEnumerable. (разрешение использования linq и/или возврата урожая).
Я думаю одна возможная ситуация, где Вы могли бы добираться, увеличение производительности состоит в том, если размер перечислимого типа и условие цикла являются константой; например:
const int ArraySize = 10;
int[] values = new int[ArraySize];
//...
for (int i = 0; i
В этом случае, в зависимости от сложности тела цикла, компилятор мог бы быть в состоянии заменить цикл встроенными вызовами. Я понятия не имею, делает ли компилятор.NET это, и это имеет ограниченную утилиту, если размер перечислимого типа является динамичным.
Одна ситуация, где foreach
мог бы работать лучше, со структурами данных как связанный список, где произвольный доступ означает пересекать список; перечислитель, используемый foreach
, вероятно, выполнит итерации одного объекта за один раз, делая каждый доступ O (1), и полный цикл O (n), но называя индексатор означает запускаться в голове и находить объект в правильном индексе; O (N) каждый цикл для O (n^2).
Лично я обычно не волнуюсь об этом и использование foreach
никакое время, я нуждаюсь во всех объектах и не забочусь об индексе объекта. Если я не работаю со всеми объектами, или я действительно должен знать индекс, я использую для. Единственное время я видел, что он был большим беспокойством, со структурами как связанные списки.
С точки зрения выделений было бы лучше посмотреть это сообщение в блоге . Это показывает в точно, при каких обстоятельствах перечислитель выделяется на "куче".
Здесь хорошая статья, которая показывает различия IL между этими двумя циклами.
Foreach технически медленнее однако намного легче использовать и легче читать. Если производительность не очень важна, я предпочитаю цикл foreach по для цикла.