Шрифт:
Интервал:
Закладка:
List<int> evenNumbers = list.FindAll(
delegate(int i)
{
return (i % 2) == 0;
}
);
Для еще большего упрощения вызова метода FindAll() могут использоваться лямбда-выражения. Во время применения синтаксиса лямбда-выражений вообще не приходится иметь дело с лежащим в основе объектом делегата. Взгляните на показанный далее новый метод в классе Program:
static void LambdaExpressionSyntax()
{
// Создать список целочисленных значений.
List<int> list = new List<int>();
list.AddRange(new int[] { 20, 1, 4, 8, 9, 44 });
<b> // Теперь использовать лямбда-выражение С #.</b>
List<int> evenNumbers = list.FindAll(i => (i % 2) == 0);
// Вывести четные числа.
Console.WriteLine("Here are your even numbers:");
foreach (int evenNumber in evenNumbers)
{
Console.Write("{0}t", evenNumber);
}
Console.WriteLine();
}
Обратите внимание на довольно странный оператор кода, передаваемый методу FindAll(), который на самом деле и представляет собой лямбда-выражение. В такой версии примера нет вообще никаких следов делегата Predicate<T> (или ключевого слова delegate, если на то пошло). Должно указываться только лямбда-выражение:
i => (i % 2) == 0
Перед разбором синтаксиса запомните, что лямбда-выражения могут использоваться везде, где должен применяться анонимный метод или строго типизированный делегат (обычно с клавиатурным набором гораздо меньшего объема). "За кулисами" компилятор C# транслирует лямбда-выражение в стандартный анонимный метод, использующий тип делегата Predicate<T> (в чем можно удостовериться с помощью утилиты ildasm.exe). Скажем, следующий оператор кода:
// Это лямбда-выражение...
List<int> evenNumbers = list.FindAll(i => (i % 2) == 0);
компилируется в приблизительно такой код С#:
// ...становится следующим анонимным методом.
List<int> evenNumbers = list.FindAll(delegate (int i)
{
return (i % 2) == 0;
});
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})Анализ лямбда-выражения
Лямбда-выражение начинается со списка параметров, за которым следует лексема => (лексема C# для лямбда-операции позаимствована из области лямбда-исчисления), а за ней — набор операторов (или одиночный оператор), который будет обрабатывать передаваемые аргументы. На самом высоком уровне лямбда-выражение можно представить следующим образом:
АргументыДляОбработки => ОбрабатывающиеОператоры
То, что находится внутри метода LambdaExpressionSyntax(), понимается так:
// i — список параметров.
// (i % 2) == 0 - набор операторов для обработки i
List<int> evenNumbers = list.FindAll(i => (i % 2) == 0);
Параметры лямбда-выражения могут быть явно или неявно типизированными. В настоящий момент тип данных, представляющий параметр i (целочисленное значение), определяется неявно. Компилятор в состоянии понять, что i является целочисленным значением, на основе области действия всего лямбда-выражения и лежащего в основе делегата. Тем не менее, определять тип каждого параметра в лямбда-выражении можно также и явно, помещая тип данных и имя переменной в пару круглых скобок, как показано ниже:
// Теперь установим тип параметров явно.
List<int> evenNumbers = list.FindAll((int i) => (i % 2) == 0);
Как вы уже видели, если лямбда-выражение имеет одиночный неявно типизированный параметр, то круглые скобки в списке параметров могут быть опущены. Если вы желаете соблюдать согласованность относительно применения параметров лямбда-выражений, тогда можете всегда заключать в скобки список параметров:
List<int> evenNumbers = list.FindAll((i) => (i % 2) == 0);
Наконец, обратите внимание, что в текущий момент выражение не заключено в круглые скобки (естественно, вычисление остатка от деления помещено в скобки, чтобы гарантировать его выполнение перед проверкой на равенство). В лямбда-выражениях разрешено заключать оператор в круглые скобки:
// Поместить в скобки и выражение.
List<int> evenNumbers = list.FindAll((i) => ((i % 2) == 0));
После ознакомления с разными способами построения лямбда-выражения давайте выясним, как его можно читать в понятных человеку терминах. Оставив чистую математику в стороне, можно привести следующее объяснение:
// Список параметров (в данном случае единственное целочисленное
// значение по имени i) будет обработан выражением (i % 2) == 0.
List<int> evenNumbers = list.FindAll((i) => ((i % 2) == 0));
Обработка аргументов внутри множества операторов
Первое рассмотренное лямбда-выражение включало единственный оператор, который в итоге вычислялся в булевское значение. Однако, как вы знаете, многие цели делегатов должны выполнять несколько операторов кода. По этой причине язык C# позволяет строить лямбда-выражения, состоящие из множества операторов, указывая блок кода в стандартных фигурных скобках. Взгляните на приведенную далее модификацию метода LambdaExpressionSyntax():
- Понимание SQL - Мартин Грубер - Базы данных