Страницы

понедельник, 4 июля 2016 г.

C# лямбда-выражения

Лямбда-выражения предназначены для определения анонимных методов в сжатой манере, тем самым еще больше упрощая работу с делегатами.


Делегаты, анонимные методы и лямбда-выражения
В качестве примера рассмотрим простой код, где нам надо получить сумму или разницу 2 целых чисел стандартным образом:
using System;
namespace SimpleLambda
{
  class Program
  {
    static void Main(string[] args)
    {
      //Стандартный способ
      Console.WriteLine("5 + 3 = {0}", Sum(5, 3));
      Console.WriteLine("5 - 3 = {0}", Sub(5, 3));

      Console.ReadLine();
    }

    //Сумма двух чисел
    public static int Sum(int x, int y)
    {
      return x + y;
    }

    //Разница двух чисел
    public static int Sub(int x, int y)
    {
      return x - y;
    }
  }
}
Результат вывода в консоль:
5 + 3 = 8
5 - 3 = 2




Но вот незадача. Иногда может потребоваться, чтобы один метод вызывал другой, проще говоря передать ему указатель на функцию. Для решения этой проблемы существуют делегаты:
using System;
namespace SimpleLambda
{
  class Program
  {
    public delegate int MathDelegate(int x, int y); //Объявим делегат, принимающий два аргумента типа int, и возвращающий int

    static void Main(string[] args)
    {
      //Стандартный способ
      Console.WriteLine("5 + 3 = {0}", Sum(5, 3));
      Console.WriteLine("5 - 3 = {0}", Sub(5, 3));

      Console.WriteLine();

      //Использование делегата
      MathDelegate md = new MathDelegate(Sum); //Передаем делегату ссылку на метод Sum
      Console.WriteLine("5 + 3 = {0}", md(5, 3)); 
      md = Sub; //Теперь передаем делегату ссылку на метод Sub
      Console.WriteLine("5 - 3 = {0}", md(5, 3));

      Console.ReadLine();
    }

    //Sums to numbers
    public static int Sum(int x, int y)
    {
      return x + y;
    }

    //Substracts two numbers
      public static int Sub(int x, int y)
    {
      return x - y;
    }
  }
}
Результат вывода на экран:
5 + 3 = 8
5 - 3 = 2

5 + 3 = 8
5 - 3 = 2


Теперь все работает как часы. Есть надобность сложить два числа - делегат с этим справится, надо получить разницу двух чисел - делегат тут как тут. Но что, если нам нужно провести комплексную операцию над двумя числами? К примеру, получить сумму двух чисел во второй степени. Создавать отдельный метод с подобной функциональностью может быть затратным по времени, особенно когда такую операцию нужно сделать всего один раз.
Начиная с C# 2.0 появилась возможность использовать анонимные методы, позволяющие передавать делегату блок кода и избежать при этом создания отдельного метода.
Итак, дополним наш пример используя анонимный метод для вычисления суммы двух чисел во второй степени:
using System;
namespace SimpleLambda
{
  class Program
  {
    public delegate int MathDelegate(int x, int y); //Объявим делегат, принимающий два аргумента типа int, и возвращающий int

    static void Main(string[] args)
    {
      //Стандартный способ
      Console.WriteLine("5 + 3 = {0}", Sum(5, 3));
      Console.WriteLine("5 - 3 = {0}", Sub(5, 3));

      Console.WriteLine();

      //Использование делегата
      MathDelegate md = new MathDelegate(Sum); //Передаем делегату ссылку на метод Sum
      Console.WriteLine("5 + 3 = {0}", md(5, 3)); 
      md = Sub; //Теперь передаем делегату ссылку на метод Sub
      Console.WriteLine("5 - 3 = {0}", md(5, 3));

      Console.WriteLine();

      //Использование анонимного метода
      md = delegate (int x, int y) { return ((x*x) + (y*y)); }; //Передаем делегату блок кода, который и является анонимным методом
      Console.WriteLine("5*5 + 3*3 = {0}", md(5, 3));

      Console.ReadLine();
    }

    //Sums to numbers
    public static int Sum(int x, int y)
    {
      return x + y;
    }

    //Substracts two numbers
    public static int Sub(int x, int y)
    {
      return x - y;
    }
  }
}
Результат вывода на экран:
5 + 3 = 8
5 - 3 = 2

5 + 3 = 8
5 - 3 = 2

5*5 + 3*3 = 34


Начиная с C# 3.0 появились лямбда-выражения, которые заменяют анонимные методы. Добавим в нашем примере лямбда-выражение, функционально идентичное анонимному методу:
using System;
namespace SimpleLambda
{
  class Program
  {
    public delegate int MathDelegate(int x, int y); //Объявим делегат, принимающий два аргумента типа int, и возвращающий int

    static void Main(string[] args)
    {
      //Стандартный способ
      Console.WriteLine("5 + 3 = {0}", Sum(5, 3));
      Console.WriteLine("5 - 3 = {0}", Sub(5, 3));

      Console.WriteLine();

      //Использование делегата
      MathDelegate md = new MathDelegate(Sum); //Передаем делегату ссылку на метод Sum
      Console.WriteLine("5 + 3 = {0}", md(5, 3)); 
      md = Sub; //Теперь передаем делегату ссылку на метод Sub
      Console.WriteLine("5 - 3 = {0}", md(5, 3));

      Console.WriteLine();

      //Использование анонимного метода
      md = delegate (int x, int y) { return ((x*x) + (y*y)); }; //Передаем делегату блок кода, который и является анонимным методом
      Console.WriteLine("5*5 + 3*3 = {0}", md(5, 3));

      Console.WriteLine();

      //Использование лямбда-выражения, вместо анонимного метода
      md = (x, y) => ((x*x) + (y*y)); //Лямбда-выражение собственной персоной
      Console.WriteLine("5*5 + 3*3 = {0}", md(5, 3));

      Console.ReadLine();
    }

    //Sums to numbers
    public static int Sum(int x, int y)
    {
      return x + y;
    }

    //Substracts two numbers
    public static int Sub(int x, int y)
    {
      return x - y;
    }
  }
}
Результат вывода на экран:
5 + 3 = 8
5 - 3 = 2

5 + 3 = 8
5 - 3 = 2

5*5 + 3*3 = 34

5*5 + 3*3 = 34


Немного о лямбда-выражениях.
Лямбда-выражения могут испугать, но сложного в них ничего нету. Вы это поймете буквально через несколько минут.
Читаются лямбда-выражения очень просто. Сначала указывается список аргументов, затем следует лямбда-оператор (=>), а после следует блок кода, который должен выполниться. Схематично это выглядит так:
список_аргументов => блок_кода
Например:
//(x, y) - список_аргументов
//((x*x) + (y*y)) - блок_кода
md = (x, y) => ((x*x) + (y*y));
Если аргументы отсутствуют, то в качестве параметров указывается пара пустых скобок:
public delegate void NewDelegate();
NewDelegate del = () => Console.WriteLine(DateTime.Now.ToString());
del(); //Выведет в консоль нынешнее дату и время
Для обработки нескольких строк, блок кода в лямбда-выражении необходимо выделить с помощью фигурных скобок:
del = () => {
Console.WriteLine("----- Some additional code -----");
Console.WriteLine(DateTime.Now.ToString());
};
Типы аргументов можно указывать, можно не указывать. Они определяются компилятором автоматически на основе сигнатуры делегата, тоже самое касается и типа возвращаемого значения.

Комментариев нет:

Отправить комментарий

ваше мнение...