Лямбда-выражения
52C# --- Руководство по C# --- Лямбда-выражения
Начиная с 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();
}
}
}