Member 12658724 Ответов: 1

Foreach против лямбда-выражения


У меня есть список типов людей. Тип людей имеет два свойства. Имя и возраст. Конечно, имя-это строковый тип, а возраст-тип int.

Теперь я хочу умножить 2 на возраст всех.

Поэтому я хочу использовать цикл foreach, каждый элемент умножить на 2.

Другой вариант-использовать лямбда-выражение.
return list.(x=>x*2);


Какой путь лучше?

Что я уже пробовал:

Мне посоветовал "эксперт". Ответ состоял в том, чтобы использовать выражение lamada, а не цикл foreach.
Но я до сих пор не нашел веской причины поддержать его.

1 Ответов

Рейтинг:
4

Graeme_Grant

Это зависит.

Вот сравнение производительности:

class Program
{
    static void Main(string[] args)
    {
        var persons = new List<Person>();
        for (int i = 0; i < 10000; i++)
        {
            persons.Add(new Person { Name = $"person {i}", age = i });
        }

        var sw = new Stopwatch();

        sw.Start();
        for (int i = 0; i < 1000; i++)
        {
            for (int j = 0; j < 10000; j++)
            {
                persons[j].age ++;
            }
        }
        sw.Stop();
        Console.WriteLine($"for loop: {sw.ElapsedMilliseconds} ms");

        sw.Reset();
        sw.Start();
        for (int i = 0; i < 1000; i++)
        {
            foreach (var person in persons)
            {
                person.age++;
            }
        }
        sw.Stop();
        Console.WriteLine($"foreach loop: {sw.ElapsedMilliseconds} ms");

        sw.Reset();
        sw.Start();
        for (int i = 0; i < 1000; i++)
        {
            persons.ForEach(person => person.age++);
        }
        sw.Stop();
        Console.WriteLine($"Linq ForEach: {sw.ElapsedMilliseconds} ms");

        Console.ReadKey();
    }
}

class Person
{
    public string Name { get; set; }
    public int age { get; set; }
}

Выход:
for loop: 453 ms
foreach loop: 527 ms
Linq ForEach: 839 ms

Легко понять, что лучше всего использовать.


Sharp Ninja

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

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

Graeme_Grant

Да, Ответ был в пределах вопроса. :)

BillWoodruff

имейте в виду, что хронометраж в .NET может быть сильно искажен:

1. запуск в режиме отладки, а не в режиме выпуска

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

3. не использовать явный контроль над сборкой мусора

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

твое здоровье, Билл