Подтвердить что ты не робот

С# Создает ли Lambda => мусор?

Использует ли lambda выражение генерировать мусор для GC, противоположного нормальному циклу foreach?

// Lambda version
Foos.ForEach(f=>f.Update(gameTime));

// Normal approach:
foreach (Foo f in Foos)
{
  f.Update(gameTime);
}

Профилировщик CLR показывает, что у меня есть 69.9% system.Action <T> , и я подозреваю, что это lamba версия петли foreach, как указано выше. Это правда?

EDIT: я использовал профилировщик Microsoft CLR: http://download.microsoft.com/download/4/4/2/442d67c7-a1c1-4884-9715-803a7b485b82/clr%20profiler.exe или http://msdn.microsoft.com/en-us/library/ff650691.aspx

4b9b3361

Ответ 1

Да, лямбда создаст мусор, если закрытие захватывает переменную из локальной области (т.е. gameTime в этом контексте).

Например, следующая функция С#:

static void TestLambda(List<Foo> Foos, DateTime gameTime)
{
    Foos.ForEach(f => f.Update(gameTime));
}

Будет переведено следующим образом:

private static void TestLambda(List<Foo> Foos, DateTime gameTime)
{
    Program.<>c__DisplayClass1 <>c__DisplayClass = new Program.<>c__DisplayClass1();
    <>c__DisplayClass.gameTime = gameTime;
    Foos.ForEach(new Action<Foo>(<>c__DisplayClass.<TestLambda>b__0));
}

Обратите внимание, что в результирующем коде есть два экземпляра new, что означает, что выделены не только Action объекты (замыкания), но также объекты для хранения захваченных переменных (экранирование записей переменных).

Ответ 2

В этом случае я думаю, что вы используете общий метод (ForEach), который будет генерировать новый тип (если предположить, что Foo является ссылочным типом, будет создан только один новый тип), и лямбда будет скомпилирована как обычный анонимный метод. Ничто в этом не говорит о линейном увеличении использования памяти.

Что касается профайлера, вы ничего не измеряете о памяти или GC. Вы измеряете время, потраченное на выполнение метода, и лямбда не должна быть значительно медленнее, чем "обычный".