Лямбда-вирази. Загальні поняття про лямбда-вирази. Лямбда-оператор. Одиночні та блочні лямбда-вирази
Зміст
- Питання/відповідь
- 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 утворити трикутник?
IT = (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; };
⇑
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² – 2·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