C# Language
Лямбда-выражения
Поиск…
замечания
Выражение лямбда является синтаксисом для создания анонимных функций inline. Более формально, из руководства по программированию на C # :
Выражение лямбда является анонимной функцией, которую можно использовать для создания делегатов или типов дерева выражений. Используя лямбда-выражения, вы можете записывать локальные функции, которые могут передаваться в качестве аргументов или возвращаться в качестве значений вызовов функций.
Выражение лямбда создается с помощью оператора =>
. Поместите любые параметры на левую сторону оператора. С правой стороны поставьте выражение, которое может использовать эти параметры; это выражение будет использоваться как возвращаемое значение функции. Реже, если необходимо, с правой стороны можно использовать целый {code block}
. Если тип возврата не является недействительным, блок будет содержать оператор return.
Передача выражения Лямбды в качестве параметра метода
List<int> l2 = l1.FindAll(x => x > 6);
Здесь x => x > 6
- это лямбда-выражение, действующее как предикат, который гарантирует, что возвращаются только элементы выше 6.
Лямбда-выражения как сокращение для инициализации делегата
public delegate int ModifyInt(int input);
ModifyInt multiplyByTwo = x => x * 2;
Вышеупомянутый синтаксис выражения Lambda эквивалентен следующему подробному коду:
public delegate int ModifyInt(int input);
ModifyInt multiplyByTwo = delegate(int x){
return x * 2;
};
Lambdas для `Func` и` Action`
Обычно lambdas используются для определения простых функций (как правило, в контексте выражения linq):
var incremented = myEnumerable.Select(x => x + 1);
Здесь return
неявно.
Тем не менее, также можно передавать действия как лямбда:
myObservable.Do(x => Console.WriteLine(x));
Лямбда-выражения с несколькими параметрами или без параметров
Используйте круглые скобки вокруг выражения слева от оператора =>
чтобы указать несколько параметров.
delegate int ModifyInt(int input1, int input2);
ModifyInt multiplyTwoInts = (x,y) => x * y;
Аналогично, пустой набор круглых скобок указывает, что функция не принимает параметры.
delegate string ReturnString();
ReturnString getGreeting = () => "Hello world.";
Положить несколько выражений в заявление лямбда
В отличие от выражения lambda, оператор lambda может содержать несколько операторов, разделенных точкой с запятой.
delegate void ModifyInt(int input);
ModifyInt addOneAndTellMe = x =>
{
int result = x + 1;
Console.WriteLine(result);
};
Обратите внимание, что инструкции заключены в фигурные скобки {}
.
Помните, что оператор lambdas не может использоваться для создания деревьев выражений.
Lambdas может излучаться как `Func`, так и` Expression`
Предполагая следующий класс Person
:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Следующая лямбда:
p => p.Age > 18
Может передаваться в качестве аргумента для обоих методов:
public void AsFunc(Func<Person, bool> func)
public void AsExpression(Expression<Func<Person, bool>> expr)
Поскольку компилятор способен преобразовывать lambdas как для делегатов, так и для Expression
.
Очевидно, что провайдеры LINQ в значительной степени полагаются на Expression
s ( IQueryable<T>
основном через интерфейс IQueryable<T>
), чтобы иметь возможность анализировать запросы и переводить их для хранения запросов.
Выражение Lambda как обработчик события
Лямбда-выражения могут использоваться для обработки событий, что полезно, когда:
- Обработчик короток.
- Обработчик никогда не должен быть отписано.
Ниже приведена хорошая ситуация, в которой может использоваться обработчик события лямбда:
smtpClient.SendCompleted += (sender, args) => Console.WriteLine("Email sent");
Если необходимо отказаться от подписывания зарегистрированного обработчика событий в какой-то будущей точке кода, выражение обработчика события должно быть сохранено в переменной, а регистрация / регистрация осуществляется через эту переменную:
EventHandler handler = (sender, args) => Console.WriteLine("Email sent");
smtpClient.SendCompleted += handler;
smtpClient.SendCompleted -= handler;
Причина, по которой это делается, а не просто повторное наложение выражения лямбда дословно, чтобы отменить подписку ( -=
), заключается в том, что компилятор C # не обязательно будет считать два выражения равными:
EventHandler handlerA = (sender, args) => Console.WriteLine("Email sent");
EventHandler handlerB = (sender, args) => Console.WriteLine("Email sent");
Console.WriteLine(handlerA.Equals(handlerB)); // May return "False"
Обратите внимание, что если к выражению лямбда добавляются дополнительные операторы, тогда требуемые окружающие фигурные скобки могут быть случайно опущены, не вызывая ошибки времени компиляции. Например:
smtpClient.SendCompleted += (sender, args) => Console.WriteLine("Email sent"); emailSendButton.Enabled = true;
Это скомпилируется, но приведет к добавлению лямбда-выражения (sender, args) => Console.WriteLine("Email sent");
как обработчик события, и выполнение инструкции emailSendButton.Enabled = true;
немедленно. Чтобы исправить это, содержимое лямбда должно быть окружено фигурными фигурными скобками. Этого можно избежать, используя фигурные скобки с самого начала, будучи осторожными при добавлении дополнительных инструкций в обработчик лямбда-события или окружающих лямбда в круглых скобках с самого начала:
smtpClient.SendCompleted += ((sender, args) => Console.WriteLine("Email sent"));
//Adding an extra statement will result in a compile-time error