Лямбда-выражения. Общие понятия о лямбда-выражениях. Лямбда-оператор. Одиночные и блочные лямбда-выражения
Содержание
- Вопрос/ответ
- 1. Какие есть способы создания анонимных функций?
- 2. Для чего в C# используются лямбда-выражения?
- 3. Что такое лямбда-оператор?
- 4. Какие существуют виды лямбда-выражений?
- 5. Какая общая форма объявления одиночного лямбда-выражения? Примеры
- 6. Какая общая форма объявления блочного лямбда-выражения? Пример
- 7. Какие действия (шаги) нужно выполнить, чтобы в программе применить лямбда-выражение? Пример
- 8. Пример использования одиночного лямбда выражения, получающего один параметр
- 9. Пример использования одиночного лямбда-выражения, которое получает несколько параметров
- 10. Пример блочного лямбда-выражения, которое получает несколько параметров
- 11. Можно ли в одном методе реализовать различные лямбда-выражения, которые соответствуют одному типу делегата?
- Связанные темы
Поиск на других ресурсах:
1. Какие есть способы создания анонимных функций?
В языке программирования C# есть два способа создания анонимных функций:
- анонимные методы;
- лямбда-выражения.
Более подробно работа анонимных методов описывается в темах:
- Анонимные функции. Анонимные методы. Возврат значения. Передача параметров
- Пример использования делегата для вызова анонимного метода. Разработка программы вычисления площади треугольника по формуле Герона
⇑
2. Для чего в C# используются лямбда-выражения?
Цель использования лямбда-выражений точно такая же как и анонимных методов. Лямбда-выражения являются альтернативой анонимным методам.
Лямбда-выражения позволяют программировать функции в упрощенном виде без использования имени с помощью специального оператора, который обозначается ‘=>’.
⇑
3. Что такое лямбда-оператор?
Лямбда-оператор обозначается ‘=>’. Дословно можно сформировать лямбда-оператор как «переходит» или «становится». Оператор ‘=>’ делит лямбда-выражение на две части.
В левой части лямбда-оператора указывается один входной параметр или несколько входных параметров. В правой части лямбда-оператора указывается лямбда выражение.
⇑
4. Какие существуют виды лямбда-выражений?
В языке C# есть две разновидности лямбда-выражений:
- одиночные лямбда-выражения;
- блочные лямбда-выражения.
⇑
5. Какая общая форма объявления одиночного лямбда-выражения? Примеры
Общая форма объявления одиночного лямбда-выражения, которое принимает один параметр:
параметр => выражение
где
- параметр – параметр, который получает на входе лямбда-выражение;
- выражение – непосредственно выражение, которое вычисляется.
Общая форма объявления одиночного лямбда-выражения, которое принимает несколько параметров:
(список_параметров) => выражение
где
- список_параметров – два и более параметра, которые используются в лямбда-выражении.
Пример 1 одиночного лямбда-выражения, которое вычисляет значение cos(x+2):
x => Math.Cos(x + 2);
В данном примере x есть входным параметром. Данное выражение заменяет функцию приблизительно следующего вида:
double CalcCos2(double x) { return Math.Cos(x + 2); }
Как видно из программного кода, использование лямбда-выражения упрощает программный код, в особенности в случаях, если нужно вызывать методы которые выполняют разную работу но имеют одинаковую сигнатуру.
Пример 2 одиночного лямбда-выражения, которое получает 3 параметра с именами a, b, c. В данном примере определяется, можно ли из длин сторон a, b, c образовать треугольник?
(a, b, c) => ((a + b) > c) && ((a + c) > b) && ((b + c) > a);
В вышеприведенном лямбда-выражении используется правило: сумма двух любых длин сторон треугольника больше длины третьей стороны.
⇑
6. Какая общая форма объявления блочного лямбда-выражения? Пример
Общая форма объявления блочного лямбда выражения, получающего один параметр:
параметр => { // инструкции, выражения // ... }
Общая форма объявления блочного лямбда-выражения, получающего несколько параметров:
(список_параметров) => { // инструкции, выражения // ... }
Пример.
В примере объявлено лямбда-выражение, которое получает параметром целое число x. В коде лямбда-выражения делается подсчет количества цифр ‘5’ в целом числе x. Например, для числа 5854 лямбда-выражение возвращает значение 2.
x => { int t, d, k; t = Math.Abs(x); k = 0; // количество цифр '5' while (t > 0) { d = t % 10; if (d == 5) k++; t = t / 10; } return k; };
Возвращение значения осуществляется оператором return.
⇑
7. Какие действия (шаги) нужно выполнить, чтобы в программе применить лямбда-выражение? Пример
Чтобы в программном коде применить лямбда-выражение, нужно выполнить следующую последовательность действий:
- Объявить тип делегата, совместный с лямбда-выражением.
- Объявить переменную этого типа делегата (экземпляр делегата).
- Присвоить переменной (экземпляру делегата) лямбда-выражение.
- Вызвать переменную (экземпляр делегата) в программном коде.
Пример. Пройдем все шаги последовательно для задачи из предшествующего пункта (п.6). Пусть нужно продемонстрировать работу лямбда-выражения, которое получает входным параметром целое число x и вычисляет количество цифр ‘5’ в этом числе.
1. Объявить тип делегата. Тип делегата объявляется в некотором классе.
// Объявить тип делегата delegate int CalcNum5(int x);
Имя типа делегата CalcNum5. Делегат этого типа будет получать один входной параметр (x). Делегат этого типа возвращает значение типа int.
2. Объявить переменную этого типа делегата. Переменная объявляется в некотором программном коде. Это может быть код произвольного метода класса, код обработчика события и т.п.
CalcNum5 CN;
3. Присвоить переменной лямбда-выражение. В методе объявления переменной объявляется присваивание:
CN = x => { int t, d, k; t = Math.Abs(x); k = 0; // количество цифр '5' while (t > 0) { d = t % 10; if (d == 5) k++; t = t / 10; } return k; };
Переменная может быть инициализирована лямбда-выражением сразу при ее объявлении (п.2) в соответствии с синтаксисом языка C#. В сокращенном виде это выглядит так:
CalcNum5 CN = x =>
{
...
};
4. Вызвать переменную. В том же методе где объявлено лямбда-выражение реализован вызов переменной. Имя CN – это имя делегата, который содержит лямбда-выражение.
// использование лямбда-выражения int a = 615; int res; res = CN(a); // res = 1
⇑
8. Пример использования одиночного лямбда выражения, получающего один параметр
В данном примере продемонстрировано использование лямбда-выражения, в котором вычисляется функция y = sin²x.
Сначала объявляется тип делегата, который получает один параметр типа float и возвращает значение типа float. Параметр имеет название – x. В обработчике события button1_Click() продемонстрировано использование лямбда-выражения.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace TrainLyambda { public partial class Form1 : Form { // объявить тип делегата, который получает 1 параметр и возвращает значение delegate float GetSin2X(float x); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { // Лямбда-выражение, которое получает 1 параметр и возвращает значение GetSin2X y = x => (float)(Math.Sin(x) * Math.Sin(x)); // Демонстрация использования лямбда-выражения float z; const float Pi = 3.1415f; z = y(0.0f); // z = 0 z = y((float)(Pi / 2.0)); // z = 1 z = y(0.7f); // z = 0.4150164 label1.Text = z.ToString(); } } }
⇑
9. Пример использования одиночного лямбда-выражения, которое получает несколько параметров
В данном примере, для заданных x, y вычисляется функция z = sin x² · cos y.
Чтобы объявить лямбда-выражение, сначала нужно объявить тип делегата, который получает 2 параметра и возвращает значение. Тип параметров и значения – double.
Объявление типа делегата имеет вид:
// объявить тип делегата, который получает 2 параметра и возвращает значение delegate double CalcZ(double x, double y);
Демонстрация использования лямбда-выражения из другого метода (например, обработчика события)
// Демонстрация использования лямбда-выражения // Объявить переменную типа "делегат" CalcZ Z; // объявить лямбда-выражение, которое получает 2 параметра с именами x, y Z = (x, y) => Math.Sin(x * x) - 2 * Math.Cos(y); // использовать лямбда-выражение для расчета double t; t = Z(0.0, 0.0); // t = -2 t = Z(3.3, 1.8); // t = -0.540028
⇑
10. Пример блочного лямбда-выражения, которое получает несколько параметров
Задача
Дано три разных целых числа. Реализовать лямбда-выражение, которое находит наибольшее из этих трех чисел.
Решение
Сначала объявляется тип делегата, который получает три параметра целого типа и возвращает целое значение
// тип делегата, который получает 3 целочисленных параметра и возвращает целое значение delegate int CalcMax(int a, int b, int c);
Затем, в другом программном коде, можно объявить лямбда-выражение и продемонстрировать его работу
// Объявить делегат CalcMax CM; // описать лямбда-выражение, которое получает 3 параметра x, y, z // и возвращает максимальное значение из этих параметров CM = (x, y, z) => { int max = x; if (max < y) max = y; if (max < z) max = z; return max; }; // использовать лямбда-выражение для поиска максимума int a = 8, b = 5, c = 10; int Max; Max = CM(a, b, c); // Max = 10 Max = CM(a + 8, b - 3, c + 1); // Max = 16
⇑
11. Можно ли в одном методе реализовать различные лямбда-выражения, которые соответствуют одному типу делегата?
Да, можно.
Пример.
Пусть объявлен тип делегата, получающий три параметра целого типа.
// объявление типа делегата delegate int CalcABC(int a, int b, int c);
Тогда, в обработчике события или в другом методе можно написать так:
// Объявить делегат CalcABC CM; // 1. Описать лямбда-выражение, получающее 3 параметра x, y, z // и возвращающее максимальное значение из этих параметров CM = (x, y, z) => { int max = x; if (max < y) max = y; if (max < z) max = z; return max; }; // использовать лямбда-выражение для поиска максимума int a = 8, b = 5, c = 10; int Max; Max = CM(a, b, c); // Max = 10 Max = CM(a + 8, b - 3, c + 1); // Max = 16 label1.Text = "Максимум = " + Max.ToString(); // 2. Лямбда-выражение, вычисляющее сумму 3-х чисел CM = (x, y, z) => { int s; s = z + x + y; return s; }; int sum = CM(4, 3, 2); // sum = 9 label1.Text = "Сумма чисел = " + sum.ToString(); // 3. Лямбда-выражение, вычисляющее произведение из 3-х чисел CM = (t, u, v) => { int mult = t * u * v; return mult; }; int Mult = CM(5, 3, 10); // Mult = 150 label1.Text = "Произведение = " + Mult.ToString();
В вышеприведенном программном коде для одного типа делегата CalcABC реализовано 3 лямбда-выражения, которые выполняют следующие операции над входными параметрами:
- находят максимальное значение;
- находят сумму параметров;
- находят произведение параметров.
Данный пример показывает преимущество применения делегатов в программах на C#. Делегат имеет одну сигнатуру (объявлена в типе), но в зависимости от ситуации при вызове этого делегата выполняется разная работа (программный код).
Такой подход есть эффективным при написании больших программных систем, где разные фрагменты кода (объекты) дают сигналы одному делегату о том, что нему нужно выполнить какую-то работу. Какую именно работу может выполнить делегат – определяется в зависимости от ситуации и объекта который сгенерировал сообщение. В результате генерируются так называемые события, которые обрабатываются с помощью делегатов. Рассмотрение работы событий это уже другая (следующая) тема.
⇑
Связанные темы
- Примеры лямбда-выражений, которые получают параметрами массивы чисел, структуры, классы
- Анонимные функции. Анонимные методы. Возврат значения. Передача параметров
- Понятие делегата. Объявление типа делегата. Использование делегата в программе. Групповое преобразование методов
- Примеры использования анонимного метода и лямбда-выражения в качестве события. Обработчики событий, которые используются в среде .NET