После чтения этой статьи, я не могу понять, почему используются лямбда-выражения. Справедливости ради, я не думаю, что у меня есть правильное понимание того, что представляют собой делегаты и типы дерева выражений, но я не понимаю, почему кто-то использовал бы лямбда-выражение вместо объявленной функции. Может кто-нибудь просветить меня?
Какой смысл выражения лямбды?
Ответ 1
Во-первых: краткость и локальность:
Что вы предпочитаете писать, читать и поддерживать? Это:
var addresses = customers.Select(customer=>customer.Address);
или
static private Address GetAddress(Customer customer)
{
return customer.Address;
}
... a thousand lines later ...
var addresses = customers.Select(GetAddress);
Какой смысл загромождать вашу программу сотнями или тысячами четырехстрочных функций, когда вы могли бы просто поместить нужный вам код, когда вам это нужно, в качестве короткого выражения?
Второе: lambdas закрывается по локальным областям
Что вы предпочитаете читать, писать и поддерживать, это:
var currentCity = GetCurrentCity();
var addresses = customers.Where(c=>c.City == currentCity).Select(c=>c.Address);
или
static private Address GetAddress(Customer customer)
{
return customer.Address;
}
private class CityGetter
{
public string currentCity;
public bool DoesCityMatch(Customer customer)
{
return customer.City == this.currentCity;
}
}
....
var currentCityGetter = new CityGetter();
currentCityGetter.currentCity = GetCurrentCity();
var addresses = customers.Where(currentCityGetter.DoesCityMatch).Select(GetAddress);
Весь этот досадный код написан для вас, когда вы используете лямбду.
В-третьих: Понимание запросов переписывается в lambdas для вас
Когда вы пишете:
var addresses = from customer in customers
where customer.City == currentCity
select customer.Address;
он преобразуется в синтаксис лямбда для вас. Многие люди считают этот синтаксис приятным для чтения, но нам нужен синтаксис лямбда, чтобы заставить его работать.
В-четвертых: lambdas - необязательно тип-вывод
Обратите внимание, что нам не нужно указывать тип "клиент" в понимании запроса выше или в версиях лямбда, но нам нужно указать тип формального параметра при объявлении его как статического метода. Компилятор умеет выводить тип параметра лямбда из контекста. Это делает ваш код менее избыточным и более понятным.
Пятое: Lambdas может стать деревьями выражений
Предположим, вы хотите спросить веб-сервер "отправьте мне адреса клиентов, которые живут в текущем городе". Вы хотите (1) вытащить миллион клиентов с веб-сайта и выполнить фильтрацию на своей клиентской машине или (2) отправить веб-сайту объект, который сообщает ему: "запрос содержит фильтр в текущем городе, а затем выбор адреса"? Пусть сервер выполнит работу и отправит вам только результат, который соответствует.
Деревья выражений позволяют компилятору превращать лямбда в код, который может быть преобразован в другой формат запроса во время выполнения и отправлен на сервер для обработки. Маленькие вспомогательные методы, которые выполняются на клиенте, не работают.
Ответ 2
Основная причина, по которой вы используете лямбда над объявленной функцией, - это когда вам нужно использовать кусок локальной информации в выражении делегата. Например
void Method(IEnumerable<Student> students, int age) {
var filtered = students.Where(s => s.Age == age);
...
}
Lambdas позволяет легко захватывать локальное состояние, которое должно использоваться в выражении делегата. Для этого вручную требуется много работы, потому что вам нужно объявить как функцию, так и содержащий тип для хранения состояния. Например, здесь выше, без лямбда
void Method(IEnumerable<Student> students, int age) {
var c = new Closure() { Age = age };
var filtered = students.Where(c.WhereDelegate);
...
}
class Closure {
public int age;
bool WhereDelegate(Student s) {
return s.Age == age;
}
}
Ввод этого текста утомительно и подвержен ошибкам. Лямбда-выражения автоматизируют этот процесс.
Ответ 3
Позвольте оставить деревья выражений из уравнения на данный момент и притвориться, что лямбды - это всего лишь более короткий способ записать делегатов.
Это все еще большая победа в области статически типизированных языков, таких как С#, потому что такие языки требуют большого количества кода для написания, чтобы достичь относительно простых целей. Вам нужно сравнить сортировку массива строк по длине строки? Вам нужно написать для этого метод. И вам нужно написать класс для ввода метода. И тогда хорошая практика диктует, что этот класс должен быть в собственном исходном файле. В любом, но самом маленьком проекте все это складывается. Когда мы говорим о мелочах, большинству людей нужен менее подробный путь к цели, а лямбды примерно такие же короткие, насколько это возможно.
Кроме того, lambdas может легко создавать замыкания (захватывать переменные из текущей области действия и продлевать их продолжительность жизни). Это не волшебство (компилятор делает это, создавая скрытый класс и выполняя некоторые другие преобразования, которые вы можете сделать сами), но это гораздо удобнее, чем ручная альтернатива.
И тогда есть деревья выражений: способ написать код и заставить компилятор преобразовать этот код в структуру данных, которая может быть проанализирована, изменена и даже скомпилирована во время выполнения. Это чрезвычайно мощная функция, которая открывает двери для впечатляющих функций (которые я определенно считаю LINQ). И вы получаете его "бесплатно".
Ответ 4
http://msdn.microsoft.com/en-us/magazine/cc163362.aspx
Отличная статья о том, что такое лямбда, и почему вы можете/должны использовать их.
По существу, выражение лямбда предоставляет сокращенное выражение для компилятора испускать методы и назначать их делегаты; все это сделано для вас. Польза, которую вы получаете с лямбдой выражение, которое вы не получаете от делегат/функция - это компилятор выполняет автоматический тип вывод по аргументам лямбда
Ответ 5
Они сильно используются с LINQ, на самом деле LINQ будет довольно плохим без него. Вы можете делать такие вещи, как:
Database.Table.Where(t = > t.Field == "Hello" );
Ответ 6
Они упрощают передачу простой функциональности другой функции. Например, я могу выполнить произвольную маленькую функцию для каждого элемента в списке (возможно, я хочу его скомпоновать или взять квадратный корень или так далее). Вместо того, чтобы писать новый цикл и функцию для каждой из этих ситуаций, я могу написать его один раз и применить свои произвольные функции, определенные позже для каждого элемента.
Ответ 7
Лямбда делает код коротким и сладким. Рассмотрим следующие два примера:
Открытый класс Студент
{
public string Name { get; set; }
public float grade { get; set; }
public static void failed(List<Student> studentList, isFaild fail)
{
foreach (Student student in studentList)
{
if(fail(student))
{
Console.WriteLine("Sorry" + " "+student.Name + " "+ "you faild this exam!");
}
}
}
публичный делегат bool isFaild (Student myStudent);
class Program
{
static void Main(string[] args)
{
List<Student> studentsList = new List<Student>();
studentsList .Add(new Student { ID = 101, Name = "Rita", grade = 99 });
studentsList .Add(new Student { ID = 102, Name = "Mark", grade = 48 });
Student.failed(studentsList, std => std.grade < 60); // with Lamda
}
}
private static bool isFaildMethod (Student myStudent)//без Lambda
{
if (myStudent.grade < 60)
{
return true;
}
else
{
return false;
}
}