Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

Console.WriteLine("******** Discards with Anonymous Methods ********");

Func<int,int,int> constant = delegate (int _, int _) {return 42;};

Console.WriteLine("constant(3,4)={0}",constant(3,4));

Понятие лямбда-выражений

Чтобы завершить знакомство с архитектурой событий .NET Core, необходимо исследовать лямбда-выражения. Как объяснялось ранее в главе, язык C# поддерживает возможность обработки событий "встраиваемым образом", позволяя назначать блок операторов

кода прямо событию с применением анонимных методов вместо построения отдельного метода, который должен вызываться делегатом. Лямбда-выражения всего лишь лаконичный способ записи анонимных методов, который в конечном итоге упрощает работу с типами делегатов .NET Core.

В целях подготовки фундамента для изучения лямбда-выражений создайте новый проект консольного приложения по имени

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

{

// Создать список целочисленных значений.

List<int> list = new List<int>;

list.AddRange(new int[] { 20, 1, 4, 8, 9, 44 });

//
Вызвать FindAll с применением традиционного синтаксиса делегатов.

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;

}

// Цель для делегата Predicate<>.

static bool IsEvenNumber(int i)

{

// Это четное число?

return (i % 2) == 0;

}

Здесь имеется метод (

IsEvenNumber
), который отвечает за проверку входного целочисленного параметра на предмет четности или нечетности с применением операции получения остатка от деления (
%
) языка С#. Запуск приложения приводит к выводу на консоль чисел 20, 4, 8 и 44.

Наряду с тем, что такой традиционный подход к работе с делегатами ведет себя ожидаемым образом,

IsEvenNumber
вызывается только при ограниченных обстоятельствах — в частности, когда вызывается метод
FindAll
, который возлагает на нас обязанность по полному определению метода. Если взамен использовать анонимный метод, то можно превратить это в локальную функцию и код станет значительно чище. Добавьте в класс
Program
следующий новый метод:

static void AnonymousMethodSyntax

{

// Создать список целочисленных значений.

List<int> list = new List<int>;

list.AddRange(new int[] { 20, 1, 4, 8, 9, 44 });

// Теперь использовать анонимный метод.

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>
) и обеспечивать точное соответствие списка параметров:

Поделиться с друзьями: