Учебники

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

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

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

(Input parameters) ⇒ Expression or statement block

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

y ⇒ y * y

Вышеупомянутое выражение указывает параметр с именем 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 Lambdas

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

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

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

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

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 является целым числом, и это делается путем проверки типа параметра Transformer.

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

Существуют некоторые правила, хотя использование области видимости в лямбда-выражении, например, переменные, которые инициируются в лямбда-выражении, не предназначены для отображения во внешнем методе. Существует также правило, что захваченная переменная не подлежит сборке мусора, если только делегат, ссылающийся на нее, не получает права на сборку мусора. Более того, существует правило, которое запрещает оператор 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. Ниже приведен пример использования лямбда-выражения для построения дерева выражений.

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

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

Синтаксис постановки лямбда

(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 или как анонимные методы. Хотя лямбда-выражения во многом похожи на анонимные методы, они вовсе не ограничены для использования только в качестве делегатов.

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

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

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

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

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

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