Лямбда-выражения C#: почему я должен их использовать?

я быстро прочитал Выражение Microsoft Lambda документация.

этот пример помог мне лучше понять, правда:

delegate int del(int i);
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25

тем не менее, я не понимаю, почему это такое нововведение. Это просто метод, который умирает, когда заканчивается "переменная метода", верно? Почему я должен использовать это вместо реального метода?

14 ответов


лямбда-выражения более простой синтаксис для анонимных делегатов и может использоваться везде, где может использоваться анонимный делегат. Однако обратное неверно; лямбда-выражения могут быть преобразованы в деревья выражений, что позволяет использовать много магии, например LINQ to SQL.

ниже приведен пример LINQ to Objects выражение с использованием анонимных делегатов, а затем лямбда-выражения, чтобы показать, насколько легче на глаз они являются:

// anonymous delegate
var evens = Enumerable
                .Range(1, 100)
                .Where(delegate(int x) { return (x % 2) == 0; })
                .ToList();

// lambda expression
var evens = Enumerable
                .Range(1, 100)
                .Where(x => (x % 2) == 0)
                .ToList();

лямбда-выражения и анонимные делегаты имеют преимущество перед написанием отдельной функции: они реализуют закрытие который может позволить вам передать локальное состояние функции без добавления параметров для функции или создания одноразовых объектов.

выражение деревьев являются очень мощной новой функцией C# 3.0, которая позволяет API смотреть на структуру выражения, а не просто получать ссылка на метод, который может быть выполнен. API просто должен сделать параметр делегата в Expression<T> параметр, и компилятор будет генерировать дерево выражений из лямбды вместо анонимного делегата:

void Example(Predicate<int> aDelegate);

называется так:

Example(x => x > 5);

будет:

void Example(Expression<Predicate<int>> expressionTree);

последний получит переданное представление абстрактное дерево синтаксиса это описывает выражение x > 5. LINQ to SQL полагается на это поведение, чтобы иметь возможность включите выражения C# в выражения SQL, необходимые для фильтрации / упорядочения / и т. д. на стороне сервера.


анонимные функции и выражения полезны для одноразовых методов, которые не выигрывают от дополнительной работы, необходимой для создания полного метода.

Рассмотрим пример:

 string person = people.Find(person => person.Contains("Joe"));

и

 public string FindPerson(string nameContains, List<string> persons)
 {
     foreach (string person in persons)
         if (person.Contains(nameContains))
             return person;
     return null;
 }

они функционально эквивалентны.


Я нашел их полезными в ситуации, когда я хотел объявить обработчик для события некоторого элемента управления, используя другой элемент управления. Чтобы сделать это нормально, вам придется хранить ссылки элементов управления в полях класса, чтобы вы могли использовать их в другом методе, чем они были созданы.

private ComboBox combo;
private Label label;

public CreateControls()
{
    combo = new ComboBox();
    label = new Label();
    //some initializing code
    combo.SelectedIndexChanged += new EventHandler(combo_SelectedIndexChanged);
}

void combo_SelectedIndexChanged(object sender, EventArgs e)
{
    label.Text = combo.SelectedValue;
}

благодаря лямбда-выражениям вы можете использовать его следующим образом:

public CreateControls()
{
    ComboBox combo = new ComboBox();
    Label label = new Label();
    //some initializing code
    combo.SelectedIndexChanged += (s, e) => {label.Text = combo.SelectedValue;};
}

гораздо проще.


лямбда очистил синтаксис анонимного делегата C# 2.0...например

Strings.Find(s => s == "hello");

было сделано в C# 2.0 вроде этого:

Strings.Find(delegate(String s) { return s == "hello"; });

функционально, они делают то же самое, только гораздо более лаконичный синтаксис.


Это всего лишь один из способов использования лямбда-выражения. Вы можете использовать лямбда-выражение в любом месте вы можете использовать делегат. Это позволяет вам делать такие вещи:

List<string> strings = new List<string>();
strings.Add("Good");
strings.Add("Morning")
strings.Add("Starshine");
strings.Add("The");
strings.Add("Earth");
strings.Add("says");
strings.Add("hello");

strings.Find(s => s == "hello");

этот код будет искать в списке запись, которая соответствует слову "привет". Другой способ сделать это-фактически передать делегат методу Find, например:

List<string> strings = new List<string>();
strings.Add("Good");
strings.Add("Morning")
strings.Add("Starshine");
strings.Add("The");
strings.Add("Earth");
strings.Add("says");
strings.Add("hello");

private static bool FindHello(String s)
{
    return s == "hello";
}

strings.Find(FindHello);

редактировать:

В C# 2.0 это можно сделать с помощью анонимного делегата синтаксис:

  strings.Find(delegate(String s) { return s == "hello"; });

лямбда значительно очистил этот синтаксис.


Microsoft дала нам более чистый и удобный способ создания анонимных делегатов, называемых лямбда-выражениями. Тем не менее, не так много внимания уделяется выражения часть этого заявления. Microsoft выпустила целое пространство имен,


Это избавляет от необходимости иметь методы, которые используются только один раз в определенном месте с определенными далеко от места их использования. Хорошее использование в качестве компараторов для общих алгоритмов, таких как сортировка, где вы можете определить пользовательскую функцию сортировки, где вы вызываете сортировку, а не дальше заставляя вас искать в другом месте, чтобы увидеть, что вы сортируете.

и это не совсем новшество. LISP имеет лямбда-функции около 30 лет или больше.


лямбда-выражение похоже на анонимный метод, написанный вместо экземпляра делегата.

delegate int MyDelagate (int i);
MyDelagate delSquareFunction = x => x * x;

рассмотрим лямбда-выражение x => x * x;

значение входного параметра равно x (слева от =>)

логика функции x * x (справа от =>)

код лямбда-выражения может быть блоком оператора вместо выражения.

x => {return x * x;};

пример

Примечание: Func - это стандартный универсальный делегат.

    Console.WriteLine(MyMethod(x => "Hi " + x));

    public static string MyMethod(Func<string, string> strategy)
    {
        return strategy("Lijo").ToString();
    }

ссылки

  1. как можно использовать делегат и интерфейс взаимозаменяемо?

вы также можете найти использование лямбда-выражений при написании общих кодов для действий с вашими методами.

например: общая функция для вычисления времени, занятого вызовом метода. (т. е. Action здесь)

public static long Measure(Action action)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    action();
    sw.Stop();
    return sw.ElapsedMilliseconds;
}

и вы можете вызвать вышеуказанный метод, используя лямбда-выражение следующим образом,

var timeTaken = Measure(() => yourMethod(param));

выражение позволяет получить возвращаемое значение из вашего метода и из param, а также

var timeTaken = Measure(() => returnValue = yourMethod(param, out outParam));

много раз вы используете функциональность только в одном месте, поэтому создание метода просто загромождает класс.


лямбда-выражение-это краткий способ представления анонимного метода. Как анонимные методы, так и лямбда-выражения позволяют определить встроенную реализацию метода, однако анонимный метод явно требует определения типов параметров и возвращаемого типа для метода. Лямбда-выражение использует функцию вывода типа C# 3.0, которая позволяет компилятору вывести тип переменной в зависимости от контекста. Это очень удобно, потому что экономит нам много печатаю!


Это способ взять небольшую операцию и поместить ее очень близко к тому, где она используется (не в отличие от объявления переменной, близкой к ее точке использования). Это должно сделать ваш код более читаемым. Анонимизируя выражение, вы также делаете намного сложнее для кого-то сломать ваш клиентский код, если он используется в другом месте и модифицируется для его "улучшения".

аналогично, почему вам нужно использовать foreach? Вы можете делать все в foreach с помощью простого цикла for или просто используя IEnumerable напрямую. Ответ: нет!--3-->нужно но это делает ваш код более читабельным.


инновации в безопасности и прозрачности. Хотя типы лямбда-выражений не объявляются, они выводятся и могут использоваться средствами поиска кода, статического анализа, рефакторинга и отражения среды выполнения.

например, прежде чем вы могли бы использовать SQL и могли бы получить атаку SQL-инъекции, потому что хакер передал строку, где обычно ожидалось число. Теперь вы будете использовать выражение LINQ lambda, которое защищено от что.

построение API LINQ на чистых делегатах невозможно, поскольку перед их оценкой требуется объединить деревья выражений.

в 2016 году большинство популярных языков лямбда-выражение поддержка и C# был одним из пионеров в этой эволюции среди основных императивных языках.


Это, пожалуй, лучшее объяснение того, почему использовать лямбда-выражения -> https://youtu.be/j9nj5dTo54Q

В общем, это улучшить читаемость кода, уменьшить вероятность ошибок путем повторного использования, а не репликации кода, и использовать оптимизацию происходит за кулисами.