На это есть те же два ответа, что и на большинство вопросов «что быстрее»:
1) Если вы не измеряете, вы не знаете.
2) (потому что ...) Это зависит.
Это зависит от того, насколько дорогой метод "MoveNext ()", относительно того, насколько дорогой метод "this [int index]", для типа (или типов) IEnumerable, который вы будете перебирать.
Ключевое слово "foreach" является сокращением для ряда операций - оно вызывает GetEnumerator () один раз в IEnumerable, оно вызывает MoveNext () один раз за итерацию, выполняет некоторую проверку типов и так далее. Наиболее вероятным фактором, влияющим на измерения производительности, является стоимость MoveNext (), поскольку она вызывается O (N) раз. Может быть, это дешево, но, возможно, это не так.
Ключевое слово "for" выглядит более предсказуемым, но внутри большинства циклов "for" вы найдете что-то вроде "collection [index]". Это похоже на простую операцию индексации массива, но на самом деле это вызов метода, стоимость которого полностью зависит от природы коллекции, для которой вы выполняете итерацию. Возможно, это дешево, но, возможно, это не так.
Если базовая структура коллекции, по сути, является связанным списком, MoveNext очень дешев, но индексатор может иметь стоимость O (N), что составляет истинную стоимость цикла "for" O (N * N).