На самом деле это две совершенно разные вещи. «Делегат» - это имя переменной, которая содержит ссылку на метод или лямбду, а лямбда - это метод без постоянного имени.
Лямбды очень похожи на другие методы, за исключением пары тонких различий.
- Обычный метод определен в «выражении» и привязан к постоянному имени, тогда как лямбда определяется «на лету» в «выражении» и не имеет постоянное имя.
- Некоторые лямбда-выражения можно использовать с деревьями выражений .NET, а методы - нет.
Делегат определяется следующим образом:
delegate Int32 BinaryIntOp(Int32 x, Int32 y);
Переменной типа BinaryIntOp может быть назначен либо метод, либо labmda, если сигнатура одна и та же: два аргумента Int32 и возврат Int32.
Лямбда может быть определена так:
BinaryIntOp sumOfSquares = (a, b) => a*a + b*b;
Следует также отметить, что хотя общие типы Func и Action часто рассматриваются как «лямбда-типы», они аналогичны любым другим делегатам. Приятно, что они по существу определяют имя для любого типа делегата, который вам может понадобиться (до 4 параметров, хотя вы, конечно, можете добавить и свой собственный). Поэтому, если вы используете широкий спектр типов делегатов, но не более одного раза, вы можете избежать загромождения своего кода объявлениями делегатов с помощью Func и Action.
Вот иллюстрация того, как Func и Action "не только для лямбд":
Int32 DiffOfSquares(Int32 x, Int32 y)
{
return x*x - y*y;
}
Func<Int32, Int32, Int32> funcPtr = DiffOfSquares;
Еще одна полезная вещь, которую нужно знать, это то, что типы делегатов (не сами методы) с одинаковой подписью, но разными именами не будут неявно приводиться друг к другу. Это включает в себя делегатов Func и Action. Однако, если подпись идентична, вы можете явно привести между ними.
Пройдя лишнюю милю .... В C # функции гибкие, с использованием лямбд и делегатов. Но в C # нет «первоклассных функций». Вы можете использовать имя функции, назначенное переменной-делегату, чтобы по существу создать объект, представляющий эту функцию. Но это действительно трюк с компилятором. Если вы начнете оператор, написав имя функции, за которым следует точка (т. Е. Попытайтесь получить доступ к элементам самой функции), вы обнаружите, что там нет членов, на которые можно ссылаться. Даже те, что из Object. Это не позволяет программисту делать полезные (и потенциально опасные) вещи, такие как добавление методов расширения, которые могут быть вызваны для любой функции. Лучшее, что вы можете сделать, - это расширить сам класс Delegate, что, безусловно, также полезно, но не так сильно.
Обновление: см. Также Ответ Карга , иллюстрирующий разницу между анонимными делегатами и методами & лямбдами.
Обновление 2: Джеймс Харт делает важное, хотя и очень техническое замечание, что лямбды и делегаты не являются сущностями .NET (т. Е. В CLR нет понятия делегата или лямбды), а скорее рамки и языковые конструкции.