Страницы

Поиск по вопросам

среда, 31 октября 2018 г.

Различие анонимных методов и lambda

В чем различие между анонимными методами и lambda-выражениями? В анонимных методах мы можем обойтись без параметров, если даже это и ожидается:
public event EventHandler SomeEvent; ... SomeEvent += delegate { Console.WriteLine("some information") };
Какие еще есть плюсы/минусу у анонимных методов и lambda-выражениями?


Ответ

Разница в том, что лямбда, в зависимости от контекста использования, может быть скомпилирована в две совершенно разных вещи:
Если контекст подразумевает использование лямбды как анонимного метода - лямбда компилируется в анонимный метод.
Func filter = x => x > 2;
будет превращено компилятором в то же, во что он превратит
Func filter = delegate(int x) { return x > 2 };
Т.е. в этом варианте использования - лямбды - это просто сокращенный вариант старого синтаксиса анонимных методов. Именно в таком виде они внедрены в Java / C++ и остальных языках, которые "добавили лямбды" за последние пару лет.
В той же Java лямбды - это единственный способ объявить анонимный метод. До введения лямбд в Java были анонимные классы (анонимные реализации интерфейсов), но не было анонимных методов - что сделало написание современного кода с промисами (аналогом Task) дико неудобным. Введение анонимных методов ("лямбд") значительно упростило написание цепочек тасков с коллбеками.
В C# синтаксис анонимных методов был введен в 2.0, в 2005-ом году, цепочки промисов можно делать уже больше десяти лет, так что что лямбды в качестве альтернативного синтаксиса ключевому слову delegate картины не изменили. Вводились лямбды совсем не ради него.
В этом варианте использования различия между лямбдами и delegate {} минимальны - на уровне "тут меньше скобок". Никаких принципиальных различий или значительных преимуществ между двумя синтаксисами нет.

Если контекст подразумевает использование лямбды в виде значения типа Expression, то лямбда компилируется не в анонимный метод, а объект-композит, представляющий код лямбды в виде AST:
Expression> filter = x => x > 2;
превращается в
ParameterExpression paramX = Expression.Parameter(typeof(int));
Expression> filter = Expression.Lambda>( Expression.GreaterThan( paramX, Expression.Constant(2) ), paramX );
Такое представление позволяет в рантайме преобразовывать выражения из кода (x > 2) в код на другом языке (SQL: WHERE table.ColumnX > 2, OData: $filter=x>2).
Именно из-за этого варианта использования и ввели лямбды в C#, и именно за счет него работают LINQ-провайдеры вроде Entity Framework.

Комментариев нет:

Отправить комментарий