Лямбда-вирази (керівництво з програмування в c #), microsoft docs

В цій статті

Лямбда-вираз - це анонімна функція. за допомогою якої можна створювати типи делегатів або дерев виразів. За допомогою лямбда-виразів можна писати локальні функції, які можна передавати в якості аргументів або повертати в якості значень з викликів функцій. Лямбда-вирази особливо корисні при написанні виразів запитів LINQ.

Щоб створити лямбда-вираз, необхідно вказати вхідні параметри (якщо вони є) з лівого боку лямбда-оператора =>. і помістити блок виразів або операторів з іншого боку. Наприклад, лямбда-вираз x => x * x задає параметр з ім'ям x і повертає значення x. Можна призначити цей вислів типу делегата, як показано в наступному прикладі:

Створення типу дерева виразів:

Оператор => має такий же пріоритет, як і присвоювання (=), і є правоассоціатівним (див. Розділ "Асоціативність" статті про операторів).

Лямбда-оператори використовуються в запитах LINQ на основі методів в якості аргументів стандартних методів операторів запиту, таких як Where.

При використанні синтаксису на основі методів для виклику методу Where в класі Enumerable (як це робиться в LINQ на об'єкти і LINQ to XML) параметром є тип делегата System.Func. Лямбда-вираз - це найбільш зручний спосіб створення делегата. При виклику того ж методу, наприклад, в класі System.Linq.Queryable (як це робиться в LINQ to SQL) типом параметра буде System.Linq.Expressions.Expression. де Func - це будь-які делегати Func з числом вхідних параметрів не більше шістнадцяти. Знову ж, лямбда-вирази являють собою найшвидший спосіб побудови дерева виразів. Лямбда-вирази дозволяють викликам Where виглядати однаково, хоча насправді об'єкт, створений з лямбда-вирази, має інший тип.

Зверніть увагу: в наведеному вище прикладі сигнатура делегата має один неявний вхідний параметр типу int і повертає значення типу int. Лямбда-вираз можна перетворити в делегат відповідного типу, оскільки він також має один вхідний параметр (x) і повертає значення, яке компілятор може неявно перетворити в тип int. (Висновок типів більш детально розглядається в наступних розділах.) Делегат, що викликається за допомогою вхідного параметра 5, повертає результат 25.

Лямбда-вирази можна використовувати з лівого боку оператора is або as.

Всі обмеження, що застосовуються до анонімних методів, застосовуються також до лямбда-виразів. Додаткові відомості див. У розділі Анонімні методи.

Вирази-лямбда

Лямбда-вираз з виразом з правої сторони оператора => називається виразом-лямбда. Вирази-лямбда широко використовуються при конструюванні дерев виразів. Вирази-лямбда повертають результат виразу і приймають наступну основну форму.

Якщо лямбда-вираз має тільки один вхідний параметр, дужки можна не ставити; у всіх інших випадках вони є обов'язковими. Два і більше вхідних параметра розділяються комами і полягають в дужки:

Іноді компілятору буває важко або навіть неможливо визначити вхідні типи. В цьому випадку типи можна вказати в явному вигляді, як показано в наступному прикладі.

Нульове кількість вхідних параметри задається порожніми дужками:

Зверніть увагу, що тіло вираження-лямбда може складатися з виклику методу, як було показано в попередньому прикладі. Однак при створенні дерев виразів, які обчислюються поза .NET Framework, наприклад в SQL Server, не слід використовувати виклики методів в лямбда-виразах. Ці методи не мають сенсу поза контекстом середовища CLR .NET.

лямбда операторів

Лямбда оператора нагадує вислів-лямбда, за винятком того, що оператор (або оператори) полягає в фігурні дужки:

Тіло лямбда оператора може складатися з будь-якої кількості операторів; однак на практиці зазвичай використовується не більше двох-трьох.

Лямбда операторів, як і анонімні методи, не можуть використовуватися для створення дерев виразів.

Асинхронні лямбда-вирази

За допомогою ключових слів async і await можна легко створювати лямбда-вирази й оператори, що включають асинхронну обробку. Наприклад, в наступному прикладі Windows Forms міститься обробник подій, який викликає асинхронний метод ExampleMethodAsync і очікує його.

Такий же обробник подій можна додати за допомогою асинхронного лямбда-вирази. Щоб додати цей обробник, поставте модифікатор async перед списком параметрів лямбда-вирази, як показано в наступному прикладі.

Лямбда зі стандартними операторами запитів

Багато стандартні оператори запитів мають вхідний параметр, тип якого належить до сімейства Func універсальних делегатів. Ці делегати використовують параметри типу для визначення кількості і типів вхідних параметрів, а також тип значення делегата. Делегати Func дуже корисні для інкапсуляції призначених для користувача виразів, які застосовуються до кожного елементу в наборі вихідних даних. Як приклад розглянемо наступний тип делегата.

Примірник цього делегата можна створити як Func myFunc. де int - вхідний параметр, а bool - повертається значення. Значення, що повертається завжди вказується в останньому параметрі типу. Func визначає делегат з двома вхідними параметрами, int і string. і типом значення, що повертається bool. Наступний делегат Func при виклику повертає значення true або false, яке показує, дорівнює чи вхідний параметр 5.

Також лямбда-вирази можна використовувати, коли аргумент має тип Expression. наприклад в стандартних операторах запитів, як зазначено в System.Linq.Queryable. При визначенні аргументу Expression лямбда компілюється в дерево виразів.

Нижче показаний метод Count. є стандартним оператором запиту.

Компілятор може вивести тип вхідного параметра введення; але його також можна визначити явно. Дане лямбда-вираз підраховує зазначені цілі значення (n), які при діленні на два дають залишок 1.

Наступний рядок коду створює послідовність, яка містить всі елементи масиву numbers. розташовані зліва від 9, оскільки це перше число послідовності, що не задовольняє умові:

Цей приклад демонструє, як визначити кілька вхідних параметрів шляхом їх ув'язнення в дужки. Цей метод повертає всі елементи в масиві чисел до того числа, величина якого менше номера його позиції. Не слід плутати лямбда-оператор (=>) з оператором "більше або дорівнює" (> =).

Висновок типу в лямбда-виразах

При написанні лямбда-виразів звичайно не потрібно вказувати тип вхідних параметрів, оскільки компілятор може виводити цей тип на основі тіла лямбда-вирази, типу делегата параметра і інших чинників, як описано в специфікації мови C #. Для більшості стандартних операторів запитів першої вхідний значення має тип елементів у вихідній послідовності. Тому при запиті IEnumerable вхідна змінна вважається об'єктом Customer. а це означає, що у вас є доступ до його методів і властивостей.

Загальні правила для лямбда-виразів формулюються наступним чином:

лямбда-вираз має містити стільки ж побільшало параметрів, що і тип делегата;

кожен вхідний параметр в лямбда-виразі повинен бути неявно перетворюється в відповідний параметр делегата;

яке значення лямбда-вирази (якщо таке є) має бути неявно перетворюється в повертається тип делегата.

Зверніть увагу: лямбда-вирази самі по собі не мають типу, оскільки в системі загальних типів спочатку відсутнє поняття "лямбда-вирази". Однак іноді буває зручно оперувати поняттям "типу" стосовно лямбда-виразів. При цьому під типом розуміється тип делегата або тип Expression. в який перетворюється лямбда-вираз.

Область дії змінної в лямбда-виразах

Лямбда-вирази можуть посилатися на зовнішні змінні (див. Розділ Анонімні методи), що знаходяться в області методу, в якому визначена лямбда-функція, або в області типу, який містить лямбда-вираз. Змінні, отримані таким способом, зберігаються для використання в лямбда-виразах, навіть якби в іншому випадку вони виявилися за межами області дії і будете знищені складальником сміття. Зовнішня змінна повинна бути певним чином присвоєна, перш ніж вона зможе використовуватися в лямбда-виразах. У наступному прикладі демонструються ці правила.

Наступні правила застосовні до області дії змінної в лямбда-виразах.

Захоплена змінна не буде знищена збирачем сміття до тих пір, поки делегат, який на неї посилається, не перейде в статус підлягає знищенню при складанні сміття.

Змінні, що вводяться в лямбда-виразі, невидимі в зовнішньому методі.

Лямбда-вираз не може безпосередньо захоплювати параметри ref або out з методу, в якому вони знаходяться.

Оператор return в лямбда-виразі не викликає повернення значення зовнішнім методом.

Лямбда-вираз не може містити оператора goto. оператора break або оператора continue всередині лямбда-функції, якщо цільовий об'єкт переходу знаходиться поза блоком. Якщо цільовий об'єкт знаходиться всередині блоку, то наявність оператора переходу за межами лямбда-функції також буде помилкою.

Специфікація мови C #

Додаткові відомості див. У специфікації мови C #. Специфікація мови є розпорядчим джерелом інформації про синтаксис і використанні мови C #.

Важлива глава книги