С# Создает ли 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
Ответы
Ответ 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. Вы измеряете время, потраченное на выполнение метода, и лямбда не должна быть значительно медленнее, чем "обычный".