Язык программирования C#9 и платформа .NET5
Часть 248 из 642 Информация о книге
В целях подготовки фундамента для изучения лямбда-выражений создайте новый проект консольного приложения по имени
. Для начала взгляните на методLambdaExpressionsобобщенного классаFindAll(). Данный метод можно вызывать, когда нужно извлечь подмножество элементов из коллекции; вот его прототип:List<T>// Метод класса System.Collections.Generic.List<T>.public List<T> FindAll(Predicate<T> match)Как видите, метод
возвращает новый объектFindAll(), который представляет подмножество данных. Также обратите внимание, что единственным параметромList<T>является обобщенный делегат типаFindAll(), способный указывать на любой метод, который возвращаетSystem.Predicate<T>и принимает единственный параметр:bool// Этот делегат используется методом FindAll()// для извлечения подмножества.public delegate bool Predicate<T>(T obj);Когда вызывается
, каждый элемент вFindAll()передается методу, указанному объектомList<T>. Реализация упомянутого метода будет выполнять некоторые вычисления для проверки соответствия элемента данных заданному критерию, возвращая в результатеPredicate<T>илиtrue. Если метод возвращаетfalse, то текущий элемент будет добавлен в новый объектtrue, который представляет интересующее подмножество.List<T>Прежде чем мы посмотрим, как лямбда-выражения могут упростить работу с методом
, давайте решим задачу длинным способом, используя объекты делегатов непосредственно. Добавьте в классFindAll()метод (Program), который взаимодействует с типомTraditionalDelegateSyntax()для обнаружения четных чисел в спискеSystem.Predicate<T>целочисленных значений:List<T>using System;using System.Collections.Generic;using LambdaExpressions;Console.WriteLine("***** Fun with Lambdas *****\n");TraditionalDelegateSyntax();Console.ReadLine();static void TraditionalDelegateSyntax(){<b> // Создать список целочисленных значений.</b>List<int> list = new List<int>();list.AddRange(new int[] { 20, 1, 4, 8, 9, 44 });<b> // Вызвать FindAll() с применением традиционного синтаксиса делегатов.</b>Predicate<int> callback = IsEvenNumber;List<int> evenNumbers = list.FindAll(callback);Console.WriteLine("Here are your even numbers:");foreach (int evenNumber in evenNumbers){Console.Write("{0}\t", evenNumber);}Console.WriteLine();}<b>// Цель для делегата Predicate<>.</b>static bool IsEvenNumber(int i){// Это четное число?return (i % 2) == 0;}Здесь имеется метод (
), который отвечает за проверку входного целочисленного параметра на предмет четности или нечетности с применением операции получения остатка от деления (IsEvenNumber()) языка С#. Запуск приложения приводит к выводу на консоль чисел 20, 4, 8 и 44.%Наряду с тем, что такой традиционный подход к работе с делегатами ведет себя ожидаемым образом,
вызывается только при ограниченных обстоятельствах — в частности, когда вызывается методIsEvenNumber(), который возлагает на нас обязанность по полному определению метода. Если взамен использовать анонимный метод, то можно превратить это в локальную функцию и код станет значительно чище. Добавьте в классFindAll()следующий новый метод:Programstatic void AnonymousMethodSyntax(){<b> // Создать список целочисленных значений.</b>List<int> list = new List<int>();list.AddRange(new int[] { 20, 1, 4, 8, 9, 44 });<b> // Теперь использовать анонимный метод.</b>List<int> evenNumbers =list.FindAll(delegate(int i) { return (i % 2) == 0; } );// Вывести четные числаConsole.WriteLine("Here are your even numbers:");foreach (int evenNumber in evenNumbers){Console.Write("{0}\t", evenNumber);}Console.WriteLine();}В данном случае вместо прямого создания объекта делегата
и последующего написания отдельного метода есть возможность определить метод как анонимный. Несмотря на шаг в правильном направлении, вам по-прежнему придется применять ключевое словоPredicate<T>(или строго типизированный классdelegate) и обеспечивать точное соответствие списка параметров:Predicate<T>