Лямбда-выражение — это анонимная функция, с помощью которой можно создавать типы делегатов или деревьев выражений. С помощью лямбда-выражений можно написать локальные функции, которые затем можно передавать в другие функции в качестве аргументов или возвращать из них в качестве значения. Лямбда-выражения особенно полезны при написании выражений запросов LINQ.
Для создания лямбда-выражения можно определить входные параметры (если таковые имеются) слева лямбда-оператора => и поместить выражение или блок операторов на другую сторону. Например, лямбда-выражение x => x * x принимает параметр с именем x и возвращает значение x, возведённое в квадрат. Можно назначить это выражение типу делегата, как показано в следующем примере:
delegate int del(int i);
static void Main(string[] args)
{
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25
}
Создание типа дерева выражений:
using System.Linq.Expressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Expression<del> myET = x => x * x;
}
}
}
Оператор => имеет такой же приоритет, как и присваивание (=), и является правоассоциативным (см. раздел "Ассоциативность" статьи об операторах).
Лямбда-операторы используются в запросах LINQ с синтаксисом на основе методов в качестве аргументов методов стандартных операторов запроса, таких как Where.
При использовании синтаксиса на основе методов для вызова метода Where класса Enumerable (как это происходит в LINQ to Objects и LINQ to XML) параметром является тип делегата System.Func<T, TResult>. Лямбда-выражение — это наиболее удобный способ создания такого делегата. При вызове того же метода, к примеру, в классе Queryable (как это делается в LINQ to SQL) типом параметра будет Expression<Func>, где Func — это любые делегаты Func с числом входных параметров не более шестнадцати.Опять же, лямбда-выражения представляют собой самый быстрый способ построения такого дерева выражений. Лямбда-выражения позволяют вызовам Where выглядеть одинаково, хотя, на самом деле, объекты, созданные из лямбда-выражений, будут иметь разные типы.
Обратите внимание: в приведённом выше примере сигнатура делегата имеет один неявный входной параметр типа int и возвращает значение типа int. Лямбда-выражение можно преобразовать в делегат соответствующего типа, поскольку он также имеет один входной параметр (x) и возвращает значение, которое компилятор может неявно преобразовать в тип int. (Вывод типов более подробно рассматривается в следующих разделах.) Делегат, вызываемый посредством входного параметра 5, возвращает результат 25.
Лямбда-выражения не разрешены в левой части оператора is или as.
Все ограничения, применяемые к анонимным методам, применяются также к лямбда-выражениям. Дополнительные сведения см. в разделе Анонимные методы (Руководство по программированию в C#).
Лямбда-выражение с выражением с правой стороны оператора => называется выражением-лямбдой. Выражения-лямбды широко используются при создании таких конструкций как Деревья выражений (C# и Visual Basic). Выражения-лямбды возвращают результат выражения и имеют следующую основную форму:
(input parameters) => expression
Если лямбда имеет только один входной параметр, скобки можно не ставить, во всех остальных случаях они обязательны. Если входных параметров два и более, то они разделяются запятыми и заключаются в скобки:
Иногда компилятору бывает трудно или даже невозможно вывести типы входных параметров. В этом случае типы можно указать в явном виде, как показано в следующем примере:
(int x, string s) => s.Length > x
Отсутствие входных параметров задаётся пустыми скобками.
Обратите внимание на предыдущий пример: тело выражения-лямбды может состоять из вызова метода. Однако при создании деревьев выражений, которые вычисляются вне .NET Framework, например в SQL Server, не следует использовать вызовы методов в лямбда-выражениях. Эти методы не имеют смысла вне контекста среды CLR .NET.
Можно легко создавать лямбда-выражения и операторы, которые включают асинхронную обработку с помощью ключевых слов async и await направит. Например, следующий фрагмент приложения Windows Forms содержит обработчик событий, который вызывает и ожидает асинхронный метод — ExampleMethodAsync:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
// ExampleMethodAsync returns a Task.
await ExampleMethodAsync();
textBox1.Text += "\r\nControl returned to Click event handler.\r\n";
}
async Task ExampleMethodAsync()
{
// The following line simulates a task-returning asynchronous process.
await Task.Delay(1000);
}
}
Можно переписать этот обработчик событий, используя асинхронное лямбда-выражение. Чтобы добавить этот обработчик, добавьте модификатор async перед списком параметров лямбда-выражения как показано в следующем примере:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
button1.Click += async (sender, e) =>
{
// ExampleMethodAsync returns a Task.
await ExampleMethodAsync();
textBox1.Text += "\r\nControl returned to Click event handler.\r\n";
};
}
async Task ExampleMethodAsync()
{
// The following line simulates a task-returning asynchronous process.
await Task.Delay(1000);
}
}
Дополнительные сведения о создании и использовании асинхронных методов см. в разделе Асинхронное программирование с использованием ключевых слов Async и Await (C# и Visual Basic).
Следующая страница