Лямбда-выражения

52

Начиная с 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();
        }
    }
}
Использование блочных лямбда-выражений
Пройди тесты
Лучший чат для C# программистов