В.NET, которую цикл выполняет быстрее, 'для' или 'foreach'?

Security Warning: этот ответ не соответствует лучшим рекомендациям по безопасности. Эвакуация неадекватна для предотвращения SQL-инъекции , вместо этого используйте подготовленные операторы . Используйте стратегию, изложенную ниже, на свой страх и риск. (Кроме того, mysql_real_escape_string() был удален в PHP 7.)

Вы могли бы сделать что-то основное:

$safe_variable = mysql_real_escape_string($_POST["user-input"]);
mysql_query("INSERT INTO table (column) VALUES ('" . $safe_variable . "')");

Это не решит каждую проблему, но это очень хороший ступень. Я оставил очевидные элементы, такие как проверка существования переменной, числа (числа, буквы и т. Д.).

320
задан 12 revs, 3 users 67% 13 June 2012 в 06:30
поделиться

31 ответ

Patrick Smacchia занесенный в блог об этом в прошлом месяце, со следующими заключениями:

  • для циклов в Списке являются больше чем в 2 раза более дешевыми, чем циклы foreach в Списке.
  • Цикличное выполнение на массиве является приблизительно в 2 раза более дешевым, чем цикличное выполнение в Списке.
  • Как следствие, цикличное выполнение на использовании массива для является в 5 раз более дешевым, чем цикличное выполнение в Списке с помощью foreach (которому я верю, то, что все мы делаем).
328
ответ дан Ian Nelson 23 November 2019 в 00:58
поделиться

Jeffrey Richter говорил различие в производительности между для и foreach на недавнем подкасте: http://pixel8.infragistics.com/shows/everything.aspx#Episode:9317

3
ответ дан Chuck Conway 23 November 2019 в 00:58
поделиться

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

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

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

2
ответ дан JohannesH 23 November 2019 в 00:58
поделиться

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

2
ответ дан Craig Gidney 23 November 2019 в 00:58
поделиться

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

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

3
ответ дан GeekyMonkey 23 November 2019 в 00:58
поделиться

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

3
ответ дан Tarik 23 November 2019 в 00:58
поделиться

Во-первых, встречное требование к ответ Dmitry . Для массивов компилятор 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

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

156
ответ дан Community 23 November 2019 в 00:58
поделиться

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

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

49
ответ дан Peter Mortensen 23 November 2019 в 00:58
поделиться

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

34
ответ дан Brian Rasmussen 23 November 2019 в 00:58
поделиться

Между двумя вряд ли будет огромное различие в производительности. Как всегда, когда сталкивающийся с, "который быстрее?" вопрос, необходимо всегда думать, что "Я могу измерить это".

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

30
ответ дан Greg Hewgill 23 November 2019 в 00:58
поделиться

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

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

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

foreach (int i in myCollection)

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

for (int i = 0; i < myCollection.Length, i++)
7
ответ дан Alex York 23 November 2019 в 00:58
поделиться

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

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

7
ответ дан Peter Mortensen 23 November 2019 в 00:58
поделиться

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

«Я пришел, чтобы узнать на протяжении многих лет компилятор C # для меня в основном лгал ". .. " Он лжет о многих вещах. ".." Например, когда вы выполняете цикл foreach ... ".." ... это одна маленькая строчка кода, которую вы пишете, но то, что компилятор C # выплевывает для этого это феноменально. Он помещает там блок try / finally, внутри блока finally он приводит вашу переменную к интерфейсу IDisposable, и если приведение завершается успешно, он вызывает на нем метод Dispose, внутри цикла он повторно вызывает свойство Current и метод MoveNext внутри цикла под крышками создаются объекты. Многие люди используют foreach, потому что это очень легко кодировать, очень легко делать ... ".." foreach не очень хорош с точки зрения производительности, если вы перебираете коллекцию вместо этого, используя нотацию квадратных скобок, просто выполняя index, это просто намного быстрее, и это не так http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032292286&EventCategory=3&culture=en-US&CountryCode=US

17
ответ дан 23 November 2019 в 00:58
поделиться

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

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

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

30
ответ дан 23 November 2019 в 00:58
поделиться

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

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

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

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

11
ответ дан 23 November 2019 в 00:58
поделиться

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

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

12
ответ дан 23 November 2019 в 00:58
поделиться

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

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

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

3
ответ дан 23 November 2019 в 00:58
поделиться

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

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

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

3
ответ дан 23 November 2019 в 00:58
поделиться

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

Используйте класс 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

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

51
ответ дан 23 November 2019 в 00:58
поделиться

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

4
ответ дан 23 November 2019 в 00:58
поделиться

Циклы foreach демонстрируют более конкретное намерение, чем для циклов .

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

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

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

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

где каждый элемент на самом деле имеет индекс.

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

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

где каждый элемент на самом деле имеет индекс.

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

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

155
ответ дан 23 November 2019 в 00:58
поделиться

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

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

7
ответ дан 23 November 2019 в 00:58
поделиться

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

.
5
ответ дан 23 November 2019 в 00:58
поделиться

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

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

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

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

6
ответ дан 23 November 2019 в 00:58
поделиться

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

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);
}

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

10
ответ дан 23 November 2019 в 00:58
поделиться

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

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

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

5
ответ дан 23 November 2019 в 00:58
поделиться

Really screw with his head and go for a IQueryable .foreach closure instead:

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

LOL

3
ответ дан 23 November 2019 в 00:58
поделиться

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

1
ответ дан Peter Mortensen 23 November 2019 в 00:58
поделиться

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

0
ответ дан David Božjak 23 November 2019 в 00:58
поделиться

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

0
ответ дан 23 November 2019 в 00:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: