Какой цикл работает быстрее в .NET: for или foreach?

Какой цикл работает быстрее в C# / VB.NET / .NET, for или foreach?

С тех пор, как я прочитал, что цикл for работает быстрее, чем цикл foreach a давным-давно, я предположил, что он верен для всех коллекций, общих коллекций, всех массивов и т. д.

Я поискал в Google и нашел несколько статей, но большинство из них неубедительны (читайте комментарии к статьям) и не имеют окончательного ответа.

Было бы идеально, если бы каждый сценарий был указан в списке и было бы лучшее решение для него.

Например (просто пример того, как должно быть):

  1. для итерации массива из 1000+ струны - for лучше, чем foreach
  2. для перебора строк IList (не универсальных) - лучше foreach чем for

Несколько ссылок на то же самое в Интернете:

  1. Оригинальная великая старая статья Эммануэля Шанцера
  2. CodeProject FOREACH Vs. ДЛЯ
  3. Блог - К foreach или не к foreach, вот в чем вопрос
  4. Форум ASP.NET - NET 1.1 C# for против foreach

[Редактировать]

Помимо аспекта удобочитаемости, меня действительно интересуют факты и цифры. Есть приложения, для которых важна последняя миля оптимизации производительности.

Разница все еще существует. В частности, массивы должны быть такими же быстрыми при использовании foreach, но для всего остального простые циклы быстрее. Конечно, в большинстве случаев это не имеет значения, и, конечно же, умный JIT-компилятор теоретически может устранить разницу.

jalf 14.12.2008 01:53

Я вижу три решения: (1) Напишите компилятор, который перечисляет в случайном порядке (2) переименуйте «foreach» в «ForEachInStrictOrder» (3) Переименуйте себя в ~ Ian, возможно, Iain?

Ian Hopkinson 23.01.2009 12:58

Без контекста я не могу точно знать, что вы делаете, но что происходит, когда вы сталкиваетесь с частично заполненным массивом?

Chris Cudmore 22.12.2009 18:18

Кстати, 2 миллиона просмотров в месяц - это ничего страшного. В среднем это меньше, чем попаданий в секунду.

mmx 22.12.2009 18:46

См. Также stackoverflow.com/questions/1723855/…

Wim Coenen 22.12.2009 19:43

Из публикации своей темы (которая оказалась для меня очень полезной) я узнал, что вы должны использовать foreach, когда вам не нужно ссылаться на индекс в коллекции. В противном случае используйте для. Это одно хорошее решение

PositiveGuy 24.12.2009 00:38
Важная заметка: Вчера этот вопрос был объединен с совершенно не связанным с ним вопросом о том, как заставить использовать foreach вместо for в C#. Если вы видите здесь ответы, которые не имеют никакого смысла, то вот почему. Винить модератора, а не неудачных ответов.
T.E.D. 27.05.2010 17:35

В общем, for будет быстрее, чем foreach. Однако, если вам не все равно, у вас, вероятно, есть «другие проблемы», более важные ...

Thomas Hansen 17.02.2009 20:04

@ТЕД. О, мне было интересно, откуда берутся все комментарии «твой босс - идиот», спасибо

Gaspa79 21.07.2016 20:27
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
380
10
227 853
41
Перейти к ответу Данный вопрос помечен как решенный

Ответы 41

Я предполагаю, что это, вероятно, не будет иметь значения в 99% случаев, так почему бы вам выбрать более быстрый вместо наиболее подходящего (как в самом простом для понимания / обслуживания)?

@klew, если вы действительно профилируете свой код, вам не придется угадывать, какие 20% должны быть как можно быстрее. Вы, вероятно, также обнаружите, что фактическое количество петель, которые должны быть быстрыми, намного меньше. Более того, действительно ли вы говорите, что действие цикла - это то, на что вы проводите свое время, а не то, что вы на самом деле делаете в этом цикле?

tster 03.12.2009 18:47

Всегда будет рядом. Для массива иногдаfor немного быстрее, но foreach более выразителен и предлагает LINQ и т. д. В общем, придерживайтесь foreach.

Кроме того, foreach можно оптимизировать в некоторых сценариях. Например, связанный список может быть ужасен для индексатора, но может быть быстрым для foreach. Собственно, стандартный LinkedList<T> по этой причине даже не предлагает индексатор.

Так вы говорите, что LinkedList<T> компактнее, чем List<T>? И если я всегда буду использовать foreach (вместо for), мне лучше использовать LinkedList<T>?

JohnB 27.05.2010 00:00

@JohnB - не стройнее; просто другой. Например, каждый узел в связанном списке имеет дополнительные ссылки, которые не нужны для плоского массива (который также поддерживает List<T>). Тем более что дешевле вставлять / Удалить.

Marc Gravell 27.05.2010 01:37

Некоторое время назад я тестировал его, и в результате выяснилось, что петля for намного быстрее, чем петля foreach. Причина проста: цикл foreach сначала должен создать экземпляр IEnumerator для коллекции.

Не с массивом, это не так. Скомпилируйте его и посмотрите на IL :) (Это также зависит от коллекции. IIRC, List <T> использует тип значения для перечислителя.)

Jon Skeet 13.12.2008 23:34

Почему одно размещение может быть дорогим? В управляемой .NET распределения практически бесплатны, не так ли, поскольку все, что делается, - это инкремент указателя в управляемой куче, в большинстве случаев фрагментация практически отсутствует.

ApplePieIsGood 13.12.2008 23:48

не только одно выделение, но и все накладные расходы на вызов методов для MoveNext () и get_Current () для каждой итерации.

Lucas 19.05.2009 23:47

У for есть более простая логика для реализации, поэтому он быстрее, чем foreach.

Ответ принят как подходящий

Патрик Смаччиа писал об этом в блоге в прошлом месяце со следующими выводами:

  • for loops on List are a bit more than 2 times cheaper than foreach loops on List.
  • Looping on array is around 2 times cheaper than looping on List.
  • As a consequence, looping on array using for is 5 times cheaper than looping on List using foreach (which I believe, is what we all do).

Однако никогда не забывайте: «Преждевременная оптимизация - корень всех зол».

Oorang 29.05.2009 08:53

@Hardwareguy: Если вы знаете, что for работает почти неприемлемо быстрее, почему бы вам не начать использовать его вообще? Это не займет лишнего времени.

DevinB 03.09.2009 17:06

@devinb, использовать "for" сложнее, чем использовать "foreach", поскольку он добавляет код, другую переменную, условие, которое необходимо проверить, и т. д. Сколько раз вы видели постепенную ошибку в цикле "foreach" ?

tster 03.12.2009 18:45

@Hardwareguy, дай мне посмотреть, правильно ли я понял. Перебор списка с foreach занимает в 5 раз больше времени, чем перебор массива с for, и вы называете это несущественным? Такая разница в производительности может иметь значение для вашего приложения, а может и нет, но я бы не стал сразу отказываться от нее.

Robert Harvey 23.12.2009 03:04

Читая сообщение в блоге, похоже, что тесты проводились в отладке, а не в выпуске, так что это может иметь значение. Кроме того, разница заключается только в накладных расходах цикла. Это вообще не влияет на время выполнения тела цикла, которое в большинстве случаев намного дольше, чем время, необходимое для перехода к следующему элементу списка. Полезно знать, когда вы определили, что проблема явно существует, и вы измерили разницу в конкретном приложении, и есть заметное улучшение, но определенно не общий совет по удалению всех foreach.

Davy8 27.05.2010 17:26
foreach может быть дешевле, чем for loop с LinkedList
gdoron is supporting Monica 17.01.2012 10:53

изображения в этой ссылке не работают, вот архивная копия web.archive.org/web/20140827024150/http://codebetter.com/…

Tony 27.02.2015 00:14

@ Davy8 Я проверял текущие результаты в режиме выпуска с помощью секундомера. Результаты изменились с тех пор, как была написана эта статья. 1. Цикл List <int> почти в 7 раз быстрее цикла foreach. Было выполнено 100 000 000 ^ 2 итераций. Ибо с оптимизированным подсчетом - самый быстрый, но почти нет разницы с примером без оптимизации (без оптимизации: 326; для оптимизированного подсчета: 296; foreach 2356). 2. Но что интереснее. В некоторых случаях для int [] foreach немного быстрее, чем for (без оптимизации: 294; для оптимизированного числа: 294; foreach 267, меньше!). 10 ^ 8 ^ 2 оперов тоже.

Anton Lyhin 08.11.2015 20:36

@gdoron Я знаю, что вы имели в виду включение поиска по индексу, но цикл for (n = l.First; n != null; n = n.Next) находится примерно на полпути между циклом foreach и соответствующим циклом for на основе массива.

Mark Hurd 01.06.2016 19:05

Вы не можете заменить более дешевое на более быстрое (если вы это имеете в виду). было бы яснее

barlop 23.09.2016 08:48

@ Ян Нельсон: В статье Джексонданстан ForEach - Назначение не выполнено. Я изменил код и выполнил, как вы упомянули, результаты не были изменены ... Спасибо: -0)

Thulasiram 04.07.2017 14:44

Стоит ли добавлять уточнение к этому ответу; то есть переключение с foreach в списке на for в массиве (в большинстве случаев) не улучшит производительность вашего кода в 5 раз, как подразумевается. Если бы все, что вы делали, было зацикливанием, это было бы правдой, но тогда вы могли бы улучшить производительность бесконечно, полностью пропустив цикл. Если у вас есть код внутри цикла, он все равно будет обрабатываться столько же времени и будет обрабатываться один раз за итерацию, что обычно делает преимущество цикла for довольно незначительным по сравнению.

JohnLBevan 07.07.2017 12:08

Различия в скорости в циклах for и foreach крошечные, когда вы просматриваете общие структуры, такие как массивы, списки и т. д., А выполнение запроса LINQ по коллекции почти всегда немного медленнее, хотя писать лучше! Как сказано на других плакатах, стремитесь к выразительности, а не к миллисекунде дополнительной производительности.

До сих пор не было сказано, что когда цикл foreach компилируется, он оптимизируется компилятором на основе коллекции, которую он повторяет. Это означает, что если вы не уверены, какой цикл использовать, вам следует использовать цикл foreach - он сгенерирует для вас лучший цикл при компиляции. Это тоже более читабельно.

Еще одно ключевое преимущество цикла foreach заключается в том, что если ваша реализация коллекции изменится (например, с int array на List<int>), то ваш цикл foreach не потребует каких-либо изменений кода:

foreach (int i in myCollection)

Вышеупомянутое одинаково независимо от типа вашей коллекции, тогда как в вашем цикле for следующее не будет построено, если вы изменили myCollection с array на List:

for (int i = 0; i < myCollection.Length, i++)

Вероятно, это зависит от типа перечисляемой коллекции и реализации ее индексатора. В целом, использование foreach, вероятно, будет лучшим подходом.

Кроме того, он будет работать с любым IEnumerable, а не только с индексаторами.

Маловероятно, что между ними будет огромная разница в производительности. Как всегда, когда сталкиваешься с вопросом "что быстрее?" вопрос, вы всегда должны думать: «Я могу это измерить».

Напишите два цикла, которые делают одно и то же, в теле цикла, выполните и синхронизируйте их оба, и посмотрите, какова разница в скорости. Сделайте это как с почти пустым телом, так и с телом цикла, аналогичным тому, что вы на самом деле будете делать. Также попробуйте это с типом коллекции, которую вы используете, потому что разные типы коллекций могут иметь разные характеристики производительности.

Во-первых, встречный иск к Ответ Дмитрия (сейчас удален). Для массивов компилятор C# генерирует в основном тот же код для foreach, что и для эквивалентного цикла for. Это объясняет, почему для этого теста результаты в основном такие же:

using System;
using System.Diagnostics;
using System.Linq;

class Test
{
    const int Size = 1000000;
    const int Iterations = 10000;

    static void Main()
    {
        double[] data = new double[Size];
        Random rng = new Random();
        for (int i=0; i < data.Length; i++)
        {
            data[i] = rng.NextDouble();
        }

        double correctSum = data.Sum();

        Stopwatch sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            double sum = 0;
            for (int j=0; j < data.Length; j++)
            {
                sum += data[j];
            }
            if (Math.Abs(sum-correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("For loop: {0}", sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            double sum = 0;
            foreach (double d in data)
            {
                sum += d;
            }
            if (Math.Abs(sum-correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("Foreach loop: {0}", sw.ElapsedMilliseconds);
    }
}

Полученные результаты:

For loop: 16638
Foreach loop: 16529

Затем проверка того, что точка Грега о важности типа коллекции - измените массив на List<double> в приведенном выше примере, и вы получите радикально другие результаты. Это не только значительно медленнее в целом, но и foreach становится значительно медленнее, чем доступ по индексу. Сказав это, я бы все же предпочел почти всегда foreach циклу for, где он упрощает код, потому что удобочитаемость почти всегда важна, а микрооптимизация - редко.

"измените массив на List <double> в приведенном выше примере, и вы получите радикально другие результаты" Очень интересно, я не думал об этом

johnc 23.01.2009 13:12

Учитывая странные различия в результатах между моими тестами и тестами других людей, я думаю, что это заслуживает публикации в блоге ...

Jon Skeet 23.01.2009 13:19

Что вы предпочитаете почти всегда между массивами и List<T>? В этом случае удобочитаемость важнее микрооптимизации?

JohnB 27.05.2010 20:18

@JohnB: Ага, я почти всегда предпочитаю List<T> массивам. Исключение составляют char[] и byte[], которые чаще рассматриваются как «фрагменты» данных, а не как обычные коллекции.

Jon Skeet 27.05.2010 20:38

Удивительно, но на моей машине разница становится еще более заметной, почти 10% в пользу foreach на простых массивах. Я дико предполагаю, что все это происходит из-за дрожания, не нужно беспокоиться о дополнительной переменной, связанных проверках и т. д. Было бы очень интересно, если бы у кого-то есть подробное объяснение этого.

Tamir Daniely 01.07.2019 00:00

Я бы посоветовал прочитать это для конкретного ответа. Вывод статьи состоит в том, что использование цикла for обычно лучше и быстрее, чем цикл foreach.

Этот вывод был написан в 2004 году. Дела пошли дальше. См. Мой тест.

Jon Skeet 23.01.2009 12:27

Если вы не участвуете в каком-либо конкретном процессе оптимизации скорости, я бы сказал, что используйте тот метод, который дает самый простой для чтения и поддержки код.

Если итератор уже настроен, например, с одним из классов коллекции, то foreach - хороший простой вариант. И если вы повторяете целочисленный диапазон, то for, вероятно, будет чище.

Джеффри Рихтер рассказал о разнице в производительности между for и foreach в недавнем подкасте: http://pixel8.infragistics.com/shows/everything.aspx#Episode:9317

Я не ожидал, что кто-то обнаружит «огромную» разницу в производительности между ними.

Я предполагаю, что ответ зависит от того, имеет ли коллекция, к которой вы пытаетесь получить доступ, более быструю реализацию доступа к индексатору или более быструю реализацию доступа к IEnumerator. Поскольку IEnumerator часто использует индексатор и просто хранит копию текущей позиции индекса, я ожидаю, что доступ к перечислителю будет как минимум таким же медленным или более медленным, чем прямой доступ к индексу, но не намного.

Конечно, этот ответ не учитывает какие-либо оптимизации, которые может реализовать компилятор.

Компилятор C# выполняет очень небольшую оптимизацию, он действительно оставляет это на усмотрение JITter.

ljs 25.01.2009 03:24

Ну, JITter - это компилятор ... Верно?

JohannesH 30.01.2009 08:41

Имейте в виду, что цикл for и цикл foreach не всегда эквивалентны. Перечислители списков вызовут исключение, если список изменится, но вы не всегда получите это предупреждение с помощью обычного цикла for. Вы можете даже получить другое исключение, если список изменится не в то время.

Если список меняется из-под вас, вы не можете полагаться на перечислитель, поддерживающий цикл foreach, чтобы сообщить вам об этом. Он не будет проверять снова после того, как вернет вам значение, что приведет к гонке.

hoodaticus 30.03.2017 20:42

Джеффри Рихтер на TechEd 2005:

"I have come to learn over the years the C# compiler is basically a liar to me." .. "It lies about many things." .. "Like when you do a foreach loop..." .. "...that is one little line of code that you write, but what the C# compiler spits out in order to do that it's phenomenal. It puts out a try/finally block in there, inside the finally block it casts your variable to an IDisposable interface, and if the cast suceeds it calls the Dispose method on it, inside the loop it calls the Current property and the MoveNext method repeatedly inside the loop, objects are being created underneath the covers. A lot of people use foreach because it's very easy coding, very easy to do.." .. "foreach is not very good in terms of performance, if you iterated over a collection instead by using square bracket notation, just doing index, that's just much faster, and it doesn't create any objects on the heap..."

Интернет-трансляция по запросу: http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032292286&EventCategory=3&culture=en-US&CountryCode=US

Петли foreach демонстрируют более конкретное намерение, чем петли for.

Использование цикла foreach демонстрирует любому, кто использует ваш код, что вы планируете что-то сделать с каждым членом коллекции, независимо от его места в коллекции. Он также показывает, что вы не изменяете исходную коллекцию (и выдает исключение, если вы попытаетесь это сделать).

Другим преимуществом foreach является то, что он работает с любым IEnumerable, тогда как for имеет смысл только для IList, где каждый элемент фактически имеет индекс.

Однако, если вам нужно использовать индекс элемента, тогда, конечно, вам должно быть разрешено использовать цикл for. Но если вам не нужно использовать индекс, его наличие просто загромождает ваш код.

Насколько мне известно, нет значительных последствий для производительности. На каком-то этапе в будущем может быть проще адаптировать код, использующий foreach, для работы на нескольких ядрах, но сейчас об этом не стоит беспокоиться.

Это очень полезно при итерации по списку настраиваемых объектов или списку данных, и вам не нужно беспокоиться обо всей номенклатуре индексов при обработке данных.

Dillie-O 22.12.2009 18:34

Я не вижу, как foreach помогает многопоточности. Я думаю, вы имеете в виду такие вещи, как Task Parallel Library, но на самом деле это не волшебство foreach.

mmx 22.12.2009 18:49

@Mehrdad Компилятор может свободно перебирать список с помощью foreach. Например, он может перебирать четные элементы на одном ядре и нечетные элементы на другом. foreach ближе к функциональному стилю программирования.

ctford 22.12.2009 18:51

ctford: Нет, это не так. Компилятор, конечно, не может переупорядочивать элементы в foreach. foreach вообще не имеет отношения к функциональному программированию. Это полностью - императивная парадигма программирования. Вы неправильно приписываете foreach то, что происходит в TPL и PLINQ.

mmx 22.12.2009 18:53

@ Mehrdad, ctford: Я думаю, это зависит от того, есть ли у foreach гарантия порядка. Если у foreach нет гарантии порядка, он может быть оптимизирован будущей версией компилятора для использования ядер, если есть что-то вроде атрибута, чтобы пометить код в цикле foreach как потокобезопасный?

BlueTrin 22.12.2009 19:05

@BlueTrin: это, безусловно, гарантирует упорядочение (раздел спецификации C# 8.8.4 формально определяет foreach как эквивалент цикла while). Думаю, я знаю, что @ctford имеет в виду. Библиотека параллельных задач позволяет основная коллекция предоставлять элементы в произвольном порядке (путем вызова .AsParallel для перечисляемого). foreach здесь ничего не делает, и тело цикла выполняется на одиночный поток. Единственное, что распараллеливается, - это генерация последовательности.

mmx 22.12.2009 19:11

@Mehrdad: Кроме того, использование foreach помогает избежать связывания кода обработки элементов с какой-либо концепцией упорядочивания, что упрощает его распараллеливание в будущем. Я преувеличил свою точку зрения - foreach - это не карта.

ctford 22.12.2009 19:17
foreach на самом деле работает с любым IEnumerable- "подобным" объектом (не столько поправкой к вашему сообщению, сколько интересным примечанием о утином наборе текста): blogs.msdn.com/kcwalina/archive/2007/07/18/DuckNotation.aspx
Sam Harwell 22.12.2009 19:25

Enumerable.Select имеет перегрузку, которая позволяет получить индекс элемента, поэтому даже необходимость в индексе не требует использования for. См. msdn.microsoft.com/en-us/library/bb534869.aspx

TrueWill 22.12.2009 21:16

ForEach удобен для удобства чтения и экономии ввода. Однако стоимость имеет значение; изменение 2 или 3 циклов for в пользовательском интерфейсе дизайнера документов, которое я создал, с (для каждого объекта в списке) на (для i = 0 в list.count-1) сократило время отклика с 2-3 секунд на редактирование до примерно. 5 секунд на редактирование небольшого документа, просто перебирая несколько сотен объектов. Теперь даже для огромных документов время на зацикливание всего не увеличивается. Понятия не имею, как это произошло. Что я точно знаю, так это то, что альтернативой была сложная схема, позволяющая зацикливать только подмножество объектов. Я возьму 5-минутную смену в любой день! - Микрооптимизация нет.

FastAl 31.03.2011 17:37

@FastAl Разница между производительностью foreach и for для обычных списков составляет доли секунды для итерации по миллионам элементов, поэтому ваша проблема определенно не связана напрямую с производительностью foreach, по крайней мере, для нескольких сотен объектов. Похоже на неработающую реализацию перечислителя в любом списке, который вы использовали.

Mike Marynowski 26.11.2017 04:38

В случаях, когда вы работаете с коллекцией объектов, лучше использовать foreach, но если вы увеличиваете число, лучше использовать цикл for.

Обратите внимание, что в последнем случае вы можете сделать что-то вроде:

foreach (int i in Enumerable.Range(1, 10))...

Но он, конечно, не работает лучше, он на самом деле имеет худшую производительность по сравнению с for.

«Лучше» можно спорить: он медленнее, и отладчик dnspy ​​не взламывает C# foreach (хотя отладчик VS2017 будет). Иногда более читабельный, но если вы поддерживаете языки без него, это может раздражать.

Zeek2 26.07.2018 12:21

Оба будут работать почти одинаково. Напишите какой-нибудь код, чтобы использовать оба, а затем покажите ему IL. Он должен показать сопоставимые вычисления, что означает отсутствие разницы в производительности.

Компилятор распознает циклы foreach, используемые для массивов / списков IL и т. д., И меняет их на циклы for.

Callum Rogers 22.12.2009 18:13

Покажите ему строчки непонятного доказательство, что это нормально, и попросите его доказательства, что это не нормально.

cjk 22.12.2009 18:45

Каждый раз, когда возникают споры по поводу производительности, вам просто нужно написать небольшой тест, чтобы вы могли использовать количественные результаты в поддержку своего дела.

Используйте класс StopWatch и для точности повторите что-нибудь несколько миллионов раз. (Это может быть сложно без цикла for):

using System.Diagnostics;
//...
Stopwatch sw = new Stopwatch()
sw.Start()
for(int i = 0; i < 1000000;i ++)
{
    //do whatever it is you need to time
}
sw.Stop();
//print out sw.ElapsedMilliseconds

Скрестив пальцы, результаты этого шоу показывают, что разница незначительна, и вы можете просто делать любые результаты в наиболее удобном для сопровождения коде.

Но вы не можете сравнивать производительность for и foreach. Их предполагается использовать в разных обстоятельствах.

Michael Krelin - hacker 22.12.2009 18:11

Я согласен с вами, Майкл, вам не следует выбирать, какой из них использовать, исходя из производительности - вы должны выбрать тот, который имеет наибольшее значение! Но если ваш босс говорит: «Не используйте for, потому что он медленнее, чем foreach», то это единственный способ убедить его, что разница незначительна.

Rob Fonseca-Ensor 22.12.2009 18:19

«(Это может быть сложно без цикла for)» Или вы можете использовать цикл while.

jonescb 22.12.2009 21:42

Это нелепо. Нет веских причин для запрета цикла for, с точки зрения производительности или чего-то еще.

См. Блог Джона Скита для теста производительности и других аргументов.

Обновленная ссылка: codeblog.jonskeet.uk/2009/01/29/…

Matt 27.10.2015 19:11

Конструкция цикла, которая работает быстрее, зависит от того, что вам нужно перебрать. Еще один блог, в котором сравнивается несколько итераций с несколькими типами объектов., например DataRows и настраиваемые объекты. Он также включает производительность конструкции цикла While, а не только конструкции цикла for и foreach.

Free Coder 24 20.05.2016 10:10

По крайней мере, я не видел, чтобы кто-либо из моих коллег или более высокопоставленных лиц говорил это, это просто смешно, учитывая тот факт, что нет значительной разницы в скорости между for и foreach. То же самое применимо, если он просит использовать его во всех случаях!

Кажется немного странным полностью запретить использование чего-то вроде цикла for.

Есть интересная статья здесь, в которой рассказывается о многих различиях в производительности между двумя циклами.

Я бы сказал, что лично я нахожу foreach более читабельным по сравнению с циклами for, но вы должны использовать лучшее для выполняемой работы и не писать слишком длинный код для включения цикла foreach, если цикл for более уместен.

Существенная цитата из статьи, на которую вы ссылаетесь: «... если вы планируете писать высокопроизводительный код, не предназначенный для коллекций, используйте цикл for. Даже для коллекций foreach может показаться удобным при использовании, но не настолько эффективным».

NickFitz 22.12.2009 19:54

В большинстве случаев разницы действительно нет.

Обычно вам всегда нужно использовать foreach, когда у вас нет явного числового индекса, и вам всегда нужно использовать, когда у вас фактически нет итерируемой коллекции (например, итерация по двумерной сетке массива в верхнем треугольнике) . В некоторых случаях у вас есть выбор.

Можно возразить, что поддерживать циклы for будет немного сложнее, если в коде начнут появляться магические числа. Вы должны быть правы, когда раздражаетесь из-за невозможности использовать цикл for и должны создавать коллекцию или использовать лямбда-выражение для создания вложенной коллекции только потому, что циклы for запрещены.

Есть очень веские причины для предпочитатьforeach зацикливания по петлям for. Если вы можете использовать петлю foreach, ваш босс прав в том, что вы должны.

Однако не каждая итерация просто просматривает список по порядку. Если он запрещающий для, да, это неправильно.

На вашем месте я бы сделал превратить все ваши естественные циклы for в рекурсию. Это его научит, а также для вас это хорошее умственное упражнение.

Как рекурсия сравнивается с циклами for и циклами foreach с точки зрения производительности?

JohnB 27.05.2010 09:18

По-разному. Если вы используете хвостовую рекурсию и ваш компилятор достаточно умен, чтобы заметить, он может быть идентичным. OTOH: Если этого не произойдет, и вы сделаете что-то глупое, например, передадите много несекретных (неизменяемых) данных в качестве параметров или объявите большие структуры в стеке как локальные, это может быть очень медленным (или даже не хватить RAM).

T.E.D. 27.05.2010 16:55

Аааа. Я понимаю, почему вы спросили об этом сейчас. Этот ответ направлен на совершенно другой вопрос. По какой-то причудливой причине Джонатан Сэмпсон вчера объединил их. Он действительно не должен был этого делать. Объединенные ответы здесь не будут иметь никакого смысла.

T.E.D. 27.05.2010 17:02

Неважно, будет ли for быстрее, чем foreach. Я серьезно сомневаюсь, что выбор одного из них существенно повлияет на вашу производительность.

Лучший способ оптимизировать ваше приложение - профилировать фактический код. Это определит методы, на которые приходится больше всего работы / времени. Оптимизируйте их в первую очередь. Если производительность по-прежнему не приемлема, повторите процедуру.

Как правило, я бы рекомендовал держаться подальше от микрооптимизаций, так как они редко приносят значительный выигрыш. Единственное исключение - оптимизация выявленных горячих путей (т.е. если при профилировании выявляются несколько часто используемых методов, может иметь смысл их обширная оптимизация).

Если бы единственный вид оптимизации, который мне нужно было делать в проектах, над которыми я работаю, - это микро-оптимизации, я был бы счастливым туристом. К сожалению, это не так.

Yannick Motton 22.12.2009 18:43
for немного быстрее, чем foreach. Я бы серьезно возражал против этого утверждения. Это полностью зависит от базовой коллекции. Если класс связанного списка предоставляет индексатор с целочисленным параметром, я бы ожидал, что использование цикла for для него будет O (n ^ 2), в то время как foreach, как ожидается, будет O (n).
mmx 22.12.2009 19:17

@Merhdad: На самом деле это хороший момент. Я как раз думал о обычном случае индексации списка (т.е. массива). Я перефразирую, чтобы отразить это. Спасибо.

Brian Rasmussen 22.12.2009 19:50

@Mehrdad Afshari: Индексирование коллекции по целому числу может быть на много медленнее, чем перечисление по ней. Но на самом деле вы сравниваете использование forа также для поиска в индексаторе с использованием самого foreach. Я думаю, что ответ @Brian Rasmussen верен, что, помимо любого использования с коллекцией, for всегда будет немного быстрее, чем foreach. Однако for плюс поиск в коллекции всегда будет медленнее, чем foreach сам по себе.

Daniel Pryden 22.12.2009 19:52

@Daniel: Либо у вас есть простой массив, для которого оба будут генерировать идентичный код, либо при использовании оператора for задействован индексатор. Обычный цикл for с целочисленной управляющей переменной несопоставим с foreach, так что его нет. Я понимаю, что имеет в виду @Brian, и, как вы говорите, это правильно, но ответ может ввести в заблуждение. Re: последнее замечание: нет, на самом деле for по сравнению с List<T> все еще быстрее, чем foreach.

mmx 22.12.2009 19:59

@ Mehrdad - Конечно, с LinkedList вы бы написали что-то вроде for (var node = list.Head; node! = Null; node = node.Next), если вы хотите использовать цикл for, сделав его O (n).

RichardOD 23.12.2009 12:06

@RichardOD: класс связанного списка, который я представлял себе, абстрагирует от вас узлы, и вы можете получить доступ к элементам с номером или с foreach;) В любом случае, моя точка зрения, строго говоря, заключается в том, что я не знаю базовой коллекции и того, как она работает , нельзя сказать, что один быстрее другого. Это все равно, что сказать, что метод A() быстрее, чем B(), не имея представления о том, что они делают.

mmx 23.12.2009 22:50

Вы действительно можете накрутить его голову и вместо этого использовать закрытие IQueryable .foreach:

myList.ForEach(c => Console.WriteLine(c.ToString());

Я бы заменил вашу строку кода на myList.ForEach(Console.WriteLine).

mmx 22.12.2009 19:16

«Есть ли какие-нибудь аргументы, которые я мог бы использовать, чтобы убедить его, что цикл for приемлем для использования?»

Нет, если ваш босс занимается микроменеджментом до уровня, говорящего вам, какие конструкции языка программирования использовать, вы действительно ничего не можете сказать. Простите.

Я думаю, что for в большинстве случаев немного быстрее, чем foreach, но это действительно упускает суть. Одна вещь, о которой я не упоминал, заключается в том, что в сценарии, о котором вы говорите (то есть в веб-приложении большого объема), разница в производительности между for и foreach не будет иметь никакого отношения к производительности сайта. Вы будете ограничены временем запроса / ответа и временем БД, а не v. Foreach.

Тем не менее, я не понимаю вашего отвращения к foreach. На мой взгляд, foreach обычно более понятен в ситуации, когда можно использовать любой из них. Я обычно прибегаю к ситуациям, когда мне нужно пройти по коллекции каким-то уродливым, нестандартным способом.

Мне нравится управлять вещами по индексу. В цикле foreach вы должны вместо этого установить переменную и увеличивать ее внутри foreach, если вам нужен счетчик. Я думаю, если вам не нужен индекс, тогда меня устраивает foreach.

PositiveGuy 23.12.2009 08:02

Это действительно так. Я просто считаю, что в большинстве сценариев я хочу «что-то сделать» с каждым элементом. Если вам нужно знать, где вы находитесь в коллекции, это определенно способ.

Sean Devlin 23.12.2009 08:29

Это то, что вы делаете внутри - цикл, который влияет на производительность, а не фактическую конструкцию цикла (при условии, что ваш случай нетривиален).

У каждой языковой конструкции есть подходящее время и место для использования. Есть причина, по которой в языке C# есть четыре отдельных операторы итерации - каждый существует для определенной цели и имеет соответствующее применение.

Я рекомендую сесть со своим начальником и попытаться рационально объяснить, почему петля for имеет цель. Бывают случаи, когда итерационный блок for более четко описывает алгоритм, чем итерация foreach. Когда это правда, их уместно использовать.

Я также хотел бы указать вашему боссу - производительность не является и не должна быть проблемой с практической точки зрения - это скорее вопрос выражения алгоритма в краткой, содержательной, поддерживаемой манере. Подобные микрооптимизации полностью упускают из виду оптимизацию производительности, поскольку любое реальное повышение производительности будет происходить от алгоритмической модернизации и рефакторинга, а не от реструктуризации цикла.

Если после рационального обсуждения эта авторитарная точка зрения все еще сохраняется, решать вам, как действовать дальше. Лично я не был бы счастлив работать в среде, где рациональное мышление не поощряется, и подумал бы о переходе на другую должность у другого работодателя. Тем не менее, я настоятельно рекомендую обсудить это, прежде чем расстраиваться - возможно, это просто недоразумение.

Это должно вас спасти:

public IEnumerator<int> For(int start, int end, int step) {
    int n = start;
    while (n <= end) {
        yield n;
        n += step;
    }
}

Использовать:

foreach (int n in For(1, 200, 4)) {
    Console.WriteLine(n);
}

Для большего выигрыша вы можете взять в качестве параметров трех делегатов.

Одно крошечное отличие состоит в том, что цикл for обычно пишется так, чтобы исключить конец диапазона (например, 0 <= i < 10). Parallel.For также делает это, чтобы его можно было легко заменить обычным шлейфом for.

Groo 24.07.2014 23:42

В моем проекте в Windows Mobile я использовал цикл for для контрольной коллекции. На 20 элементов управления ушло 100 ms! Цикл foreach использовал только 4 ms. Это была проблема с производительностью ...

Начиная с .NET Framework 4, вы также можете использовать Parallel.For и Parallel.ForEach, как описано здесь: Многопоточный цикл C# с Parallel.For или Parallel.ForEach

Обратите внимание, что ответы только по ссылке не приветствуются, ответы SO должны быть конечной точкой поиска решения (по сравнению с еще одной остановкой ссылок, которые со временем устаревают). Пожалуйста, рассмотрите возможность добавления здесь отдельного синопсиса, сохранив ссылку в качестве справочной.

kleopatra 18.12.2013 13:54

Я нашел цикл foreach, который повторяется через ListБыстрее. См. Результаты моих тестов ниже. В приведенном ниже коде я повторяю array размером 100, 10000 и 100000 отдельно, используя цикл for и foreach для измерения времени.

private static void MeasureTime()
    {
        var array = new int[10000];
        var list = array.ToList();
        Console.WriteLine("Array size: {0}", array.Length);

        Console.WriteLine("Array For loop ......");
        var stopWatch = Stopwatch.StartNew();
        for (int i = 0; i < array.Length; i++)
        {
            Thread.Sleep(1);
        }
        stopWatch.Stop();
        Console.WriteLine("Time take to run the for loop is {0} millisecond", stopWatch.ElapsedMilliseconds);

        Console.WriteLine(" ");
        Console.WriteLine("Array Foreach loop ......");
        var stopWatch1 = Stopwatch.StartNew();
        foreach (var item in array)
        {
            Thread.Sleep(1);
        }
        stopWatch1.Stop();
        Console.WriteLine("Time take to run the foreach loop is {0} millisecond", stopWatch1.ElapsedMilliseconds);

        Console.WriteLine(" ");
        Console.WriteLine("List For loop ......");
        var stopWatch2 = Stopwatch.StartNew();
        for (int i = 0; i < list.Count; i++)
        {
            Thread.Sleep(1);
        }
        stopWatch2.Stop();
        Console.WriteLine("Time take to run the for loop is {0} millisecond", stopWatch2.ElapsedMilliseconds);

        Console.WriteLine(" ");
        Console.WriteLine("List Foreach loop ......");
        var stopWatch3 = Stopwatch.StartNew();
        foreach (var item in list)
        {
            Thread.Sleep(1);
        }
        stopWatch3.Stop();
        Console.WriteLine("Time take to run the foreach loop is {0} millisecond", stopWatch3.ElapsedMilliseconds);
    }

ОБНОВЛЕНО

После предложения @jgauffin я использовал код @johnskeet и обнаружил, что цикл for с array быстрее, чем следующий,

  • Цикл по каждому элементу с массивом.
  • Для цикла со списком.
  • Цикл по каждому элементу со списком.

См. Результаты моих тестов и код ниже,

private static void MeasureNewTime()
    {
        var data = new double[Size];
        var rng = new Random();
        for (int i = 0; i < data.Length; i++)
        {
            data[i] = rng.NextDouble();
        }
        Console.WriteLine("Lenght of array: {0}", data.Length);
        Console.WriteLine("No. of iteration: {0}", Iterations);
        Console.WriteLine(" ");
        double correctSum = data.Sum();

        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < Iterations; i++)
        {
            double sum = 0;
            for (int j = 0; j < data.Length; j++)
            {
                sum += data[j];
            }
            if (Math.Abs(sum - correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("For loop with Array: {0}", sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (var i = 0; i < Iterations; i++)
        {
            double sum = 0;
            foreach (double d in data)
            {
                sum += d;
            }
            if (Math.Abs(sum - correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("Foreach loop with Array: {0}", sw.ElapsedMilliseconds);
        Console.WriteLine(" ");

        var dataList = data.ToList();
        sw = Stopwatch.StartNew();
        for (int i = 0; i < Iterations; i++)
        {
            double sum = 0;
            for (int j = 0; j < dataList.Count; j++)
            {
                sum += data[j];
            }
            if (Math.Abs(sum - correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("For loop with List: {0}", sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (int i = 0; i < Iterations; i++)
        {
            double sum = 0;
            foreach (double d in dataList)
            {
                sum += d;
            }
            if (Math.Abs(sum - correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("Foreach loop with List: {0}", sw.ElapsedMilliseconds);
    }

Это очень плохой тест. а) вы делаете слишком мало итераций, чтобы получить окончательный ответ. б) Этот Thread.Sleep на самом деле не будет ждать одну миллисекунду. Используйте тот же метод, что и Джон Скит в своем ответе.

jgauffin 12.06.2014 09:51

99,99% времени определенно тратится в thread.sleep (что не дает никаких гарантий относительно того, насколько быстро он вернется, за исключением того, что он не вернется по крайней мере до этого времени). Зацикливание происходит очень быстро, а сон очень медленный, вы не используете последнее для проверки первого.

Ronan Thibaudau 20.04.2015 15:02

Мне нужно было выполнить синтаксический анализ некоторых больших данных с помощью трех вложенных циклов (на List<MyCustomType>). Я подумал, используя сообщение Роба Фонсека-Энсора выше, было бы интересно время и сравнить разницу, используя для и для каждого.

Разница была: Foreach (три вложенных foreach, например, foreach {foreach {forech {}}} выполняли задание за 171,441 секунд, тогда как as for (for {for {for {}}}) выполняли его за 158,616 секунд.

Теперь 13 секунд - это сокращение 13% времени на это, что в некоторой степени важно для меня. Однако foreach определенно более читабелен, чем использование трех индексированных for ...

Здесь есть те же два ответа, что и на большинство вопросов "что быстрее":

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).

Бен Уотсон, автор книги «Написание высокопроизводительного кода .NET»:

"Will these optimization matter to your program? Only if your program is CPU bound and collection iteration is a core part of your processing. As you'll see, there are ways you can hurt your performance if you're not careful, but that only matters if it was a significant part of your program to begin with. My philosophy is this: most people never need to know this, but if you do, then understanding every layer of the system is important so that you can make intelligent choices".

Наиболее исчерпывающее объяснение можно найти здесь: http://www.codeproject.com/Articles/844781/Digging-Into-NET-Loop-Performance-Bounds-checking

Я упомянул об этих деталях, основываясь на скорости сбора в for и foreach.

List -For Loop немного быстрее, чем Foreach Loop

ArrayList - For Loop примерно в 2 раза быстрее, чем Foreach Loop.

Массив - оба работают с одинаковой скоростью, но цикл по каждому элементу кажется немного быстрее.

Я столкнулся со случаем, когда foreach намного быстрее, чем For

почему foreach быстрее, чем цикл for при чтении строк richtextbox

У меня был случай, похожий на OP в этом вопросе.

Текстовое поле, читающее около 72 КБ строк, и я обращался к свойству Lines (которое на самом деле является методом получения). (И, по-видимому, часто в winforms есть методы получения, которые не являются O (1). Я полагаю, что это O (n), поэтому чем больше текстовое поле, тем больше времени требуется для получения значения из этого `` свойства ''. А в for У меня был цикл, поскольку у OP был for(int i=0;i<textBox1.lines.length;i++) str=textBox1.Lines[i], и он действительно был довольно медленным, поскольку он читал все текстовое поле каждый раз, когда читал строку, плюс он читал все текстовое поле каждый раз, когда проверял условие.

Джон Скит показывает, что вы можете сделать это, обращаясь к свойству Lines только один раз (даже не один раз за итерацию, только один раз). Скорее, чем дважды на каждой итерации (а это тонна раз). Сделайте строку [] strarrlines = textBox1.Lines; и пропустите строчки.

Но, безусловно, цикл for в довольно интуитивно понятной форме и доступ к свойству Lines очень неэффективен.

for (int i = 0; i < richTextBox.Lines.Length; i++)
{
    s = richTextBox.Lines[i];
}

для текстового поля или расширенного текстового поля это очень медленно.

OP, тестируя этот цикл на расширенном текстовом поле, обнаружил, что «с 15000 строками. Для цикла for потребовалось 8 минут, чтобы просто выполнить цикл до 15000 строк. Тогда как foreach потребовалось доли секунды для его перечисления».

OP по этой ссылке обнаружил, что этот foreach намного более эффективен, чем его (тот же OP) цикл for, упомянутый выше. Как и я.

   String s=String.Empty;
   foreach(string str in txtText.Lines)
    {
       s=str;
    }

вы можете прочитать об этом в Deep .NET - часть 1, итерация

он охватывает результаты (без первой инициализации) от исходного кода .NET до разборки.

например - Итерация массива с циклом foreach:

и - итерация списка с циклом foreach:

и конечные результаты:

    internal static void Test()
    {
        int LOOP_LENGTH = 10000000;
        Random random = new Random((int)DateTime.Now.ToFileTime());

        {
            Dictionary<int, int> dict = new Dictionary<int, int>();
            long first_memory = GC.GetTotalMemory(true);
            var stopWatch = Stopwatch.StartNew();
            for (int i = 0; i < 64; i++)
            {
                dict.Add(i, i);
            }

            for (int i = 0; i < LOOP_LENGTH; i++)
            {
                for (int k = 0; k < dict.Count; k++)
                {
                    if (dict[k] > 1000000) Console.WriteLine("Test");
                }
            }
            stopWatch.Stop();
            var last_memory = GC.GetTotalMemory(true);
            Console.WriteLine($"Dictionary for T:{stopWatch.Elapsed.TotalSeconds}s\t M:{last_memory - first_memory}");

            GC.Collect();
        }


        {
            Dictionary<int, int> dict = new Dictionary<int, int>();
            long first_memory = GC.GetTotalMemory(true);
            var stopWatch = Stopwatch.StartNew();
            for (int i = 0; i < 64; i++)
            {
                dict.Add(i, i);
            }

            for (int i = 0; i < LOOP_LENGTH; i++)
            {
                foreach (var item in dict)
                {
                    if (item.Value > 1000000) Console.WriteLine("Test");
                }
            }
            stopWatch.Stop();
            var last_memory = GC.GetTotalMemory(true);
            Console.WriteLine($"Dictionary foreach T:{stopWatch.Elapsed.TotalSeconds}s\t M:{last_memory - first_memory}");

            GC.Collect();
        }

        {
            Dictionary<int, int> dict = new Dictionary<int, int>();
            long first_memory = GC.GetTotalMemory(true);
            var stopWatch = Stopwatch.StartNew();
            for (int i = 0; i < 64; i++)
            {
                dict.Add(i, i);
            }

            for (int i = 0; i < LOOP_LENGTH; i++)
            {
                foreach (var item in dict.Values)
                {
                    if (item > 1000000) Console.WriteLine("Test");
                }
            }
            stopWatch.Stop();
            var last_memory = GC.GetTotalMemory(true);
            Console.WriteLine($"Dictionary foreach values T:{stopWatch.Elapsed.TotalSeconds}s\t M:{last_memory - first_memory}");

            GC.Collect();
        }


        {
            List<int> dict = new List<int>();
            long first_memory = GC.GetTotalMemory(true);
            var stopWatch = Stopwatch.StartNew();
            for (int i = 0; i < 64; i++)
            {
                dict.Add(i);
            }

            for (int i = 0; i < LOOP_LENGTH; i++)
            {
                for (int k = 0; k < dict.Count; k++)
                {
                    if (dict[k] > 1000000) Console.WriteLine("Test");
                }
            }
            stopWatch.Stop();
            var last_memory = GC.GetTotalMemory(true);
            Console.WriteLine($"list for T:{stopWatch.Elapsed.TotalSeconds}s\t M:{last_memory - first_memory}");

            GC.Collect();
        }


        {
            List<int> dict = new List<int>();
            long first_memory = GC.GetTotalMemory(true);
            var stopWatch = Stopwatch.StartNew();
            for (int i = 0; i < 64; i++)
            {
                dict.Add(i);
            }

            for (int i = 0; i < LOOP_LENGTH; i++)
            {
                foreach (var item in dict)
                {
                    if (item > 1000000) Console.WriteLine("Test");
                }
            }
            stopWatch.Stop();
            var last_memory = GC.GetTotalMemory(true);
            Console.WriteLine($"list foreach T:{stopWatch.Elapsed.TotalSeconds}s\t M:{last_memory - first_memory}");

            GC.Collect();
        }
    }

Словарь для T: 10.1957728s M: 2080
Словарь foreach T: 10.5900586s M: 1952
Словарь для каждого значения T: 3.8294776s M: 2088
список для T: 3.7981471s M: 320
list foreach T: 4.4861377s M: 648

Другие вопросы по теме