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

Термин «лямбда-выражение» получил свое название от «лямбда-исчисления», которое, в свою очередь, представляет собой математическую нотацию, применяемую для определения функций. Лямбда-выражения как исполняемая часть уравнения LINQ транслируют логику таким образом во время выполнения, чтобы ее можно было удобно передать источнику данных. Однако лямбда-выражения не ограничиваются поиском применения только в LINQ.

Эти выражения выражаются следующим синтаксисом -

(Input parameters) ⇒ Expression or statement block

Вот пример лямбда-выражения -

у ⇒ у * у

Вышеприведенное выражение определяет параметр с именем y, и это значение y возводится в квадрат. Однако в этой форме невозможно выполнить лямбда-выражение. Пример лямбда-выражения в C # показан ниже.

C #

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace lambdaexample {
   class Program {

      delegate int del(int i);
      static void Main(string[] args) {

         del myDelegate = y ⇒ y * y;
         int j = myDelegate(5);
         Console.WriteLine(j);
         Console.ReadLine();
      }
   }
}

VB

Module Module1
   Private Delegate Function del(ByVal i As Integer) As Integer
   
   Sub Main(ByVal args As String())
   
      Dim myDelegate As del = Function(y) y * y
      Dim j As Integer = myDelegate(5)
      Console.WriteLine(j)
      Console.ReadLine()
	  
   End Sub
   
End Module

Когда приведенный выше код C # или VB компилируется и выполняется, он дает следующий результат:

25

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

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

Асинхронные лямбды

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

Func<Task<string>> getWordAsync = async()⇒ “hello”;

Лямбда в стандартных операторах запросов

Лямбда-выражение в операторе запроса оценивается тем же оператором по запросу и постоянно работает с каждым из элементов входной последовательности, а не со всей последовательностью. Лямбда-выражение позволяет разработчикам вводить собственную логику в стандартные операторы запросов. В приведенном ниже примере разработчик использовал оператор «Где» для восстановления нечетных значений из данного списка с помощью лямбда-выражения.

C #

//Get the average of the odd Fibonacci numbers in the series... 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace lambdaexample {
   class Program {     
      static void Main(string[] args) {
      
         int[] fibNum = { 1, 1, 2, 3, 5, 8, 13, 21, 34 };
         double averageValue = fibNum.Where(num ⇒ num % 2 == 1).Average();
         Console.WriteLine(averageValue);
         Console.ReadLine();
      }
   }
}

VB

Module Module1

   Sub Main()
   
      Dim fibNum As Integer() = {1, 1, 2, 3, 5, 8, 13, 21, 34}
      Dim averageValue As Double = fibNum.Where(Function(num) num Mod 2 = 1).Average()
	  
      Console.WriteLine(averageValue)
      Console.ReadLine()
	  
   End Sub
   
End Module

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

7.33333333333333

Вывод типа в лямбде

В C # вывод типа удобно использовать в различных ситуациях, причем без явного указания типов. Однако в случае лямбда-выражения вывод типа будет работать только тогда, когда каждый тип указан, поскольку компилятор должен быть удовлетворен. Рассмотрим следующий пример.

delegate int Transformer (int i);

Здесь компилятор использует вывод типа, чтобы использовать тот факт, что x является целым числом, и это делается путем проверки типа параметра преобразователя.

Область действия переменной в лямбда-выражении

Есть некоторые правила при использовании области видимости переменных в лямбда-выражении, например, переменные, которые инициируются в лямбда-выражении, не должны быть видимыми во внешнем методе. Также существует правило, согласно которому захваченная переменная не подлежит сборке мусора, если делегат, ссылающийся на нее, не получит право на сборку мусора. Более того, есть правило, запрещающее оператору return в лямбда-выражении вызывать возврат включающего метода.

Вот пример, демонстрирующий область видимости переменной в лямбда-выражении.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace lambdaexample {
   class Program {
      delegate bool D();
      delegate bool D2(int i);

      class Test {
         D del;
         D2 del2;
			
         public void TestMethod(int input) {
            int j = 0;
            // Initialize the delegates with lambda expressions.
            // Note access to 2 outer variables.
            // del will be invoked within this method.
            del = () ⇒ { j = 10; return j > input; };

            // del2 will be invoked after TestMethod goes out of scope.
            del2 = (x) ⇒ { return x == j; };

            // Demonstrate value of j:            
            // The delegate has not been invoked yet.
            Console.WriteLine("j = {0}", j);        // Invoke the delegate.
            bool boolResult = del();
           
            Console.WriteLine("j = {0}. b = {1}", j, boolResult);
         }

         static void Main() {
            Test test = new Test();
            test.TestMethod(5);

            // Prove that del2 still has a copy of
            // local variable j from TestMethod.
            bool result = test.del2(10);
           
            Console.WriteLine(result);

            Console.ReadKey();
         }
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

j = 0
j = 10. b = True
True

Дерево выражений

Лямбда-выражения используются в Expression Treeстроительство широко. Дерево выражений выдает код в структуре данных, напоминающей дерево, в котором каждый узел сам по себе является выражением, таким как вызов метода, или может быть бинарной операцией, например x <y. Ниже приведен пример использования лямбда-выражения для построения дерева выражений.

Заявление Лямбда

Есть также statement lambdasсостоят из двух или трех операторов, но не используются при построении деревьев выражений. Оператор возврата должен быть записан в лямбда-выражении оператора.

Синтаксис выражения лямбда

(params)⇒ {statements}

Пример выражения лямбда

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace lambdaexample {
   class Program {
      static void Main(string[] args) {
         int[] source = new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 };

         foreach (int i in source.Where(x ⇒ 
            {
               if (x <= 3)
                  return true;
               else if (x >= 7)
                  return true;
               return false;
            }
         ))
        Console.WriteLine(i);
        Console.ReadLine();
      }
   }
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

3
8
1
7
9
2
8

Лямбда-выражения используются в качестве аргументов в запросах LINQ на основе методов и никогда не могут находиться в левой части таких операторов, как is или же asточно так же, как анонимные методы. Хотя лямбда-выражения во многом похожи на анонимные методы, их использование не ограничивается только делегатами.

Что следует помнить при использовании лямбда-выражений

  • Лямбда-выражение может возвращать значение и иметь параметры.

  • Параметры могут быть определены множеством способов с помощью лямбда-выражения.

  • Если в лямбда-выражении есть один оператор, фигурные скобки не нужны, тогда как при наличии нескольких операторов фигурные скобки, а также возвращаемое значение необходимы для записи.

  • С помощью лямбда-выражений можно получить доступ к переменным, присутствующим вне блока лямбда-выражения, с помощью функции, известной как замыкание. Закрытие следует использовать осторожно, чтобы избежать каких-либо проблем.

  • Невозможно выполнить небезопасный код внутри любого лямбда-выражения.

  • Лямбда-выражения не предназначены для использования в левой части оператора.