Страницы

Ярлыки

ДШИ-200 (1) КСВУ-6 (1) ЛЧМ (1) МДР-23 (1) микроконтроллер (1) перенаправление (1) С (1) структуры (1) учебный курс (1) AC/DC (1) ADC (1) ADS1248 (1) Altium (1) Altuim (1) Amolifer (1) ARM (1) assembler (2) Asynchronous (1) at command (3) at#eaddr (1) at#epassw (1) at#esmtp (1) at#euser (1) at#gprs (1) at#selint=2 (1) at#sgact (1) at#tcpatcmdseq (1) ATX (1) AVR (2) bit (1) boost (1) boot (2) bootlloader (1) C (6) C# (7) C++ (1) CMSIS (1) command (1) CP2101 (1) CSD (1) Danfoss (6) DBGMCU (1) debug (1) debug.ini (1) delegate (1) Discovery (1) DMA (1) DRV8805 (1) DWT (1) e-mail (1) email (1) Exel (1) exFAT (1) FC-051 (1) gl868-dual (2) gl868-dual cmux (1) GPIO (2) GSM (1) I2C (1) IAR (1) ID (1) Invoke (1) Keil (3) LabVIEW (1) Linux (1) LMP7721 (1) LoRa (3) mdmread (1) memory (1) MODBUS (1) Operation Amplifer (1) pack (1) printf (2) printf() (1) RCC (1) retargetting (1) RFM95/96/87/98(W) (1) RS232 (4) RS485 (1) RSAPI.DLL (1) RSS (1) RTC (2) send (2) SerialPort (1) Silabs (1) spl (1) standard peripherals library (1) startup (1) stepper (2) STlink (1) STlink/V2 (2) STM32 (10) stm32 stm32f10x (1) STM32DBG.IN (1) STM32F (19) STM32F103 (4) struct (1) Structure (1) system (1) SystemInit (1) Task (1) telit (5) thread (4) TIM (1) Type Cast (1) UART (1) uni-trend (1) USART (6) USB (1) UT61B (1) viewer (1)

понедельник, 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());
};
Типы аргументов можно указывать, можно не указывать. Они определяются компилятором автоматически на основе сигнатуры делегата, тоже самое касается и типа возвращаемого значения.

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

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

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