Может быть, это поможет увидеть, как эта функция реализована вручную:
using System;
using System.Collections.Generic;
namespace CSharpSandbox
{
class Program
{
static IEnumerable<T> Where<T>(IEnumerable<T> input, Func<T, bool> predicate)
{
foreach (T item in input)
{
if (predicate(item))
yield return item;
}
}
static void Main(string[] args)
{
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
IEnumerable<int> evens = Where(numbers, n => n % 2 == 0);
foreach (int even in evens)
{
Console.WriteLine(even);
}
}
}
}
Конструкция name => someEvaluation
создает анонимную функцию, состоящую из следующих частей:
name
- это просто имя параметра, его тип определяется из его использования. Вам нужно имя, чтобы вы могли ссылаться на аргумент, переданный в функции.
=>
- это начало вашего тела анонимных функций, область видимости тела - это одно выражение.
someEvaluation
- это тело вашей анонимной функции, состоящее из одного выражения.
В нашем случае Func<T, bool>
определяет функцию, которая принимает один параметр типа T
и возвращает вывод типа bool
. (Если бы мы использовали Func<T, U, bool>
, мы бы взяли два входа типа T
и U
и вернули бы bool
. Последний параметр типа в определении Func
является возвращаемым значением.)
Вы можете вызвать экземпляр Func
точно так же, как вы вызываете любую другую функцию. Если функция принимает параметры, вы передаете их как положено, ваши параметры привязываются к именам переменных, которые вы определили. Когда вы вызываете функцию, поток управления переходит в вашу функцию и оценивает ее результаты.
В принципе вам не нужно создавать Func
анонимно. Вы можете передать любую функцию, имеющую совместимую сигнатуру типа, например:
static bool IsEven(int n)
{
return n % 2 == 0;
}
static void Main(string[] args)
{
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
IEnumerable<int> evens = Where(numbers, IsEven);
foreach (int even in evens)
{
Console.WriteLine(even);
}
}
Эта программа выдает тот же результат. Фактически, за кулисами синтаксис name => expression
является синтаксическим сахаром; после компиляции C # создаст приватную функцию со скрытым именем и преобразует ее в приведенный выше формат.