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

211
30 марта 2017, 17:59

В чем различие между анонимными методами и lambda-выражениями? В анонимных методах мы можем обойтись без параметров, если даже это и ожидается:

public event EventHandler SomeEvent;
...
SomeEvent += delegate { Console.WriteLine("some information") };

Какие еще есть плюсы/минусу у анонимных методов и lambda-выражениями?

Answer 1

Разница в том, что лямбда, в зависимости от контекста использования, может быть скомпилирована в две совершенно разных вещи:

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

Func<int, bool> filter = x => x > 2;

будет превращено компилятором в то же, во что он превратит

Func<int, bool> filter = delegate(int x) { return x > 2 };

Т.е. в этом варианте использования - лямбды - это просто сокращенный вариант старого синтаксиса анонимных методов. Именно в таком виде они внедрены в Java / C++ и остальных языках, которые "добавили лямбды" за последние пару лет.

В той же Java лямбды - это единственный способ объявить анонимный метод. До введения лямбд в Java были анонимные классы (анонимные реализации интерфейсов), но не было анонимных методов - что сделало написание современного кода с промисами (аналогом Task) дико неудобным. Введение анонимных методов ("лямбд") значительно упростило написание цепочек тасков с коллбеками.

В C# синтаксис анонимных методов был введен в 2.0, в 2005-ом году, цепочки промисов можно делать уже больше десяти лет, так что что лямбды в качестве альтернативного синтаксиса ключевому слову delegate картины не изменили. Вводились лямбды совсем не ради него.

В этом варианте использования различия между лямбдами и delegate {} минимальны - на уровне "тут меньше скобок". Никаких принципиальных различий или значительных преимуществ между двумя синтаксисами нет.

Если контекст подразумевает использование лямбды в виде значения типа Expression, то лямбда компилируется не в анонимный метод, а объект-композит, представляющий код лямбды в виде AST:

Expression<Func<int, bool>> filter = x => x > 2;

превращается в

ParameterExpression paramX = Expression.Parameter(typeof(int));
Expression<Func<int, bool>> filter = Expression.Lambda<Func<int, bool>>(
        Expression.GreaterThan(
            paramX, Expression.Constant(2)
            ),
        paramX
    );

Такое представление позволяет в рантайме преобразовывать выражения из кода (x > 2) в код на другом языке (SQL: WHERE table.ColumnX > 2, OData: $filter=x&gt2).

Именно из-за этого варианта использования и ввели лямбды в C#, и именно за счет него работают LINQ-провайдеры вроде Entity Framework.

READ ALSO
Поведение NET Flags атрибута

Поведение NET Flags атрибута

Столкнулся сегодня с загадочным поведением enum с атрибутом FlagsПервый enum из проекта, только имя изменил

256
Как вызывать по одной форме внутри Panel?

Как вызывать по одной форме внутри Panel?

Проблема в том, что вызывая Form2 она открывается несколько раз до бесконечностиМожет есть способ открывать только один раз, и при переходе...

213
Вопрос про компоновку представлений asp.net mvc

Вопрос про компоновку представлений asp.net mvc

Подход database first, есть две модели и у каждой модели по одному представлению

240
optgroup для dropdowlist

optgroup для dropdowlist

Есть такой кусок кода

148