Лямбда-выражения
Начиная с C# 3.0, доступен новый синтаксис для назначения реализации кода делегатам, называемый лямбда-выражениями (lambda expression). Лямбда-выражения могут использоваться везде, где есть параметр типа делегата.
Синтаксис лямбда-выражений проще синтаксиса анонимных методов. В случае если подлежащий вызову метод имеет параметры, а эти параметры не нужны, синтаксис анонимных методов проще, поскольку в этом случае указывать параметры не потребуется.
Во всех лямбда-выражениях применяется новый лямбда-оператор =>, который разделяет лямбда-выражение на две части. В левой его части указывается входной параметр (или несколько параметров), а в правой части — тело лямбда-выражения. Оператор => иногда описывается такими словами, как "переходит" или "становится".
В C# поддерживаются две разновидности лямбда-выражений в зависимости от тела самого лямбда-выражения. Так, если тело лямбда-выражения состоит из одного выражения, то образуется одиночное лямбда-выражение. В этом случае тело выражения не заключается в фигурные скобки. Если же тело лямбда-выражения состоит из блока операторов, заключенных в фигурные скобки, то образуется блочное лямбда-выражение. При этом блочное лямбда-выражение может содержать целый ряд операторов, в том числе циклы, вызовы методов и условные операторы if. Обе разновидности лямбда-выражений рассматриваются далее по отдельности.
Одиночные лямбда-выражения
В одиночном лямбда-выражении часть, находящаяся справа от оператора =>, воздействует на параметр (или ряд параметров), указываемый слева. Возвращаемым результатом вычисления такого выражения является результат выполнения лямбда-оператора. Ниже приведена общая форма одиночного лямбда-выражения, принимающего единственный параметр:
параметр => выражение
Если же требуется указать несколько параметров, то используется следующая форма:
(список_параметров) => выражение
Таким образом, когда требуется указать два параметра или более, их следует заключить в скобки. Если же выражение не требует параметров, то следует использовать пустые скобки.
Лямбда-выражение применяется в два этапа. Сначала объявляется тип делегата, совместимый с лямбда-выражением, а затем экземпляр делегата, которому присваивается лямбда-выражение. После этого лямбда-выражение вычисляется при обращении к экземпляру делегата. Результатом его вычисления становится возвращаемое значение. Давайте рассмотрим пример:
using System; namespace ConsoleApplication1 { // Создадим несколько делегатов имитирующих // простейшую форму регистрации delegate int LengthLogin(string s); delegate bool BoolPassword(string s1, string s2); class Program { private static void SetLogin() { Console.Write("Введите логин: "); string login = Console.ReadLine(); // Используем лямбда-выражение LengthLogin lengthLoginDelegate = s => s.Length; int lengthLogin = lengthLoginDelegate(login); if (lengthLogin > 25) { Console.WriteLine("Слишком длинное имя\n"); // Рекурсия на этот же метод, чтобы ввести заново логин SetLogin(); } } static void Main() { SetLogin(); Console.Write("Введите пароль: "); string password1 = Console.ReadLine(); Console.Write("Повторите пароль: "); string password2 = Console.ReadLine(); // Используем лямбда выражение BoolPassword bp = (s1, s2) => s1 == s2; if (bp(password1, password2)) Console.WriteLine("Регистрация удалась!"); else Console.WriteLine("Регистрация провалилась. Пароли не совпадают"); Console.ReadLine(); } } }
Блочные лямбда-выражения
Второй разновидностью лямбда-выражений является блочное лямбда-выражение. Для такого лямбда-выражения характерны расширенные возможности выполнения различных операций, поскольку в его теле допускается указывать несколько операторов. Например, в блочном лямбда-выражении можно использовать циклы и условные операторы if, объявлять переменные и т.д. Создать блочное лямбда-выражение нетрудно. Для этого достаточно заключить тело выражения в фигурные скобки. Помимо возможности использовать несколько операторов, в остальном блочное лямбда-выражение, практически ничем не отличается от только что рассмотренного одиночного лямбда-выражения.
Давайте модифицируем предыдущий пример, добавив капчу в форму регистрации:
using System; namespace ConsoleApplication1 { // Создадим несколько делегатов имитирующих // простейшую форму регистрации delegate int LengthLogin(string s); delegate bool BoolPassword(string s1, string s2); delegate void Captha(string s1, string s2); class Program { private static void SetLogin() { Console.Write("Введите логин: "); string login = Console.ReadLine(); // Используем лямбда-выражение LengthLogin lengthLoginDelegate = s => s.Length; int lengthLogin = lengthLoginDelegate(login); if (lengthLogin > 25) { Console.WriteLine("Слишком длинное имя\n"); // Рекурсия на этот же метод, чтобы ввести заново логин SetLogin(); } } static void Main() { SetLogin(); Console.Write("Введите пароль: "); string password1 = Console.ReadLine(); Console.Write("Повторите пароль: "); string password2 = Console.ReadLine(); // Используем лямбда выражение BoolPassword bp = (s1, s2) => s1 == s2; if (bp(password1, password2)) { Random ran = new Random(); string resCaptha = ""; for (int i = 0; i < 10; i++) resCaptha += (char)ran.Next(0, 100); Console.WriteLine("Введите код xD: " + resCaptha); string resCode = Console.ReadLine(); // Реализуем блочное лямбда-выражение Captha cp = (s1, s2) => { if (s1 == s2) Console.WriteLine("Регистрация удалась!"); else Console.WriteLine("Не переживай, в следующий раз получится :)"); return; }; cp(resCaptha, resCode); } else Console.WriteLine("Регистрация провалилась. Пароли не совпадают"); Console.ReadLine(); } } }
Комментарии