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

c# c#-3.0 lambda

221648 просмотра

14 ответа

Я быстро прочитал документацию Microsoft Lambda Expression .

Этот пример помог мне лучше понять:

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

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

Автор: Patrick Desjardins Источник Размещён: 12.09.2019 02:42

Ответы (14)


278 плюса

Решение

Лямбда-выражения являются более простым синтаксисом для анонимных делегатов и могут использоваться везде, где может использоваться анонимный делегат. Однако обратное неверно; Лямбда-выражения могут быть преобразованы в деревья выражений, что позволяет использовать магию, такую ​​как 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, требуемые для фильтрации / упорядочения / и т. Д. На стороне сервера.

Автор: Neil Williams Размещён: 03.10.2008 03:20

134 плюса

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

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

 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;
 }

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

Автор: Joseph Daigle Размещён: 03.10.2008 03:14

84 плюса

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

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;};
}

Намного легче.

Автор: agnieszka Размещён: 18.12.2008 06:19

35 плюса

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

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

Было сделано в C # 2.0 следующим образом:

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

Функционально они делают одно и то же, это просто более лаконичный синтаксис.

Автор: FlySwat Размещён: 03.10.2008 03:27

29 плюса

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

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"; });

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

Автор: Scott Dorman Размещён: 03.10.2008 03:20

22 плюса

Microsoft предоставила нам более чистый и удобный способ создания анонимных делегатов, называемых лямбда-выражениями. Однако не так много внимания уделяется части выражений этого утверждения. Microsoft выпустила целое пространство имен System.Linq.Expressions , которое содержит классы для создания деревьев выражений на основе лямбда-выражений. Деревья выражений состоят из объектов, которые представляют логику. Например, x = y + z - это выражение, которое может быть частью дерева выражений в .Net. Рассмотрим следующий (простой) пример:

using System;
using System.Linq;
using System.Linq.Expressions;


namespace ExpressionTreeThingy
{
    class Program
    {
        static void Main(string[] args)
        {
            Expression<Func<int, int>> expr = (x) => x + 1; //this is not a delegate, but an object
            var del = expr.Compile(); //compiles the object to a CLR delegate, at runtime
            Console.WriteLine(del(5)); //we are just invoking a delegate at this point
            Console.ReadKey();
        }
    }
}

Этот пример тривиален. И я уверен, что вы думаете: «Это бесполезно, поскольку я мог бы непосредственно создать делегат вместо создания выражения и его компиляции во время выполнения». И ты был бы прав. Но это обеспечивает основу для деревьев выражений. Существует несколько выражений, доступных в пространствах имен Expressions, и вы можете создавать свои собственные. Я думаю, вы можете видеть, что это может быть полезно, когда вы не знаете точно, каким должен быть алгоритм во время проектирования или компиляции. Я видел где-то пример использования этого для написания научного калькулятора. Вы также можете использовать его для байесовских систем или для генетического программирования(AI). Несколько раз в моей карьере мне приходилось писать функции, подобные Excel, которые позволяли пользователям вводить простые выражения (сложение, подстановки и т. Д.) Для работы с доступными данными. В pre-.Net 3.5 мне приходилось прибегать к некоторому языку сценариев, внешнему по отношению к C #, или использовать рефлексию кода для отражения, чтобы создавать код .Net на лету. Теперь я бы использовал деревья выражений.

Автор: Jason Jackson Размещён: 09.10.2008 02:23

12 плюса

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

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

Автор: workmad3 Размещён: 03.10.2008 03:14

6 плюса

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

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

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

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

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

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

var timeTaken = Measure(() => returnValue = yourMethod(param, out outParam));
Автор: Gunasekaran Размещён: 07.01.2014 10:25

5 плюса

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

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. Как делегат и интерфейс могут использоваться взаимозаменяемо?
Автор: Lijo Размещён: 20.12.2013 01:01

4 плюса

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

Автор: Darren Kopp Размещён: 03.10.2008 03:14

4 плюса

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

Автор: Vijesh VP Размещён: 03.10.2008 03:19

3 плюса

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

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

Автор: plinth Размещён: 03.10.2008 03:19

0 плюса

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

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

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

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

Автор: battlmonstr Размещён: 21.08.2016 02:56

0 плюса

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

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

Автор: coffeeeee Размещён: 19.03.2017 10:40
Вопросы из категории :
32x32