Простой тест для полу-проверки. Я сделал небольшой тест, просто чтобы посмотреть. Вот код:
static void Main(string[] args)
{
List<int> intList = new List<int>();
for (int i = 0; i < 10000000; i++)
{
intList.Add(i);
}
DateTime timeStarted = DateTime.Now;
for (int i = 0; i < intList.Count; i++)
{
int foo = intList[i] * 2;
if (foo % 2 == 0)
{
}
}
TimeSpan finished = DateTime.Now - timeStarted;
Console.WriteLine(finished.TotalMilliseconds.ToString());
Console.Read();
}
А вот раздел foreach:
foreach (int i in intList)
{
int foo = i * 2;
if (foo % 2 == 0)
{
}
}
Когда я заменил for на foreach - он был на 20 миллисекунд быстрее - последовательно . Значение for составляло 135-139 мс, а значение foreach - 113-119 мс. Я несколько раз обменивался взад-вперед, убедившись, что это не какой-то процесс, который только что включился.
Однако, когда я удалил оператор foo и if, for был быстрее на 30 мс (foreach был 88 мс, а for был 59 мс). Они оба были пустыми снарядами. Я предполагаю, что foreach фактически передал переменную, где for просто увеличивал переменную. Если бы я добавил
int foo = intList[i];
Тогда for становится медленным примерно на 30 мс. Я предполагаю, что это связано с созданием foo, захватом переменной в массиве и присвоением ее foo. Если вы просто обращаетесь к intList [i], у вас нет этого штрафа.
Честно говоря ... Я ожидал, что foreach будет немного медленнее при любых обстоятельствах, но не достаточным, чтобы иметь значение в большинстве приложений.
edit: вот новый код, использующий предложения Jons (134217728 - самое большое значение, которое вы можете получить до того, как сгенерировано исключение System.OutOfMemory):
static void Main(string[] args)
{
List<int> intList = new List<int>();
Console.WriteLine("Generating data.");
for (int i = 0; i < 134217728 ; i++)
{
intList.Add(i);
}
Console.Write("Calculating for loop:\t\t");
Stopwatch time = new Stopwatch();
time.Start();
for (int i = 0; i < intList.Count; i++)
{
int foo = intList[i] * 2;
if (foo % 2 == 0)
{
}
}
time.Stop();
Console.WriteLine(time.ElapsedMilliseconds.ToString() + "ms");
Console.Write("Calculating foreach loop:\t");
time.Reset();
time.Start();
foreach (int i in intList)
{
int foo = i * 2;
if (foo % 2 == 0)
{
}
}
time.Stop();
Console.WriteLine(time.ElapsedMilliseconds.ToString() + "ms");
Console.Read();
}
А вот и результаты:
Генерация данных.
Расчет для цикла: 2458мс
Расчет цикла foreach: 2005мс
Обменив их, чтобы посмотреть, имеет ли он дело с порядком вещей, дает те же результаты (почти).