Delegați în interogările LINQ
Dacă ne uităm la definiția multor metode de extensie LINQ, vom observa că multe dintre ele acceptă delegați ca parametru, de exemplu, Func<TSource, bool>, cum ar fi definiția metodei Where:
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate
)
De obicei, ca delegat în astfel de metode, este convenabil să se transmită expresii lambda. Cu toate acestea, putem transmite și metode complete. De exemplu:
string[] people = { "Tom", "Bob", "Kate", "Tim", "Mike", "Sam" };
var result = people.Where(LenghtIs3);
foreach (var person in result)
Console.WriteLine(person);
bool LenghtIs3(string name) => name.Length == 3;
Aici, metoda LenghtIs3 verifică dacă lungimea șirului este egală cu 3 caractere. Deoarece în acest caz setul de elemente la care se aplică metoda Where conține obiecte string, în metodă se transmite ca parametru un obiect de acest tip. Tipul returnat trebuie să fie de tip bool: dacă este true, obiectul string corespunde condiției și intră în colecția de ieșire.
Să examinăm un alt exemplu. Să presupunem că metoda Select() se aplică unei colecții de numere întregi și transformă fiecare număr în pătratul său:
int[] numbers = { -2, -1, 0, 1, 2, 3, 4, 5, 6, 7 };
var result = numbers.Where(i => i > 0).Select(Square);
foreach (int i in result)
Console.WriteLine(i);
int Square(int n) => n * n;
Metoda Select acceptă ca parametru tipul Func<TSource, TResult> selector. Deoarece avem un set de obiecte int, parametru de intrare al delegatului va fi un obiect de tip int. Ca tip de ieșire, alegem int, deoarece pătratul numărului este o valoare întreagă.