Обобщенные делегаты

Делегаты — это безопасные к типам ссылки на методы. Благодаря концепции обобщенных делегатов, параметры делегатов могут быть определены позднее.

Изменим метод Accumulate( ), чтобы он использовал два обобщенных типа. Тип TInput будет типом объектов, которые нужно накапливать, a TSummary — типом возврата. Первый параметр Accumulate( ) — интерфейс IEnumerable, как и раньше. Второй параметр требует делегата Action, который ссылается на метод, вызываемый для накопления балансов.

При реализации метод, на который ссылается делегат Action, вызывается для каждого элемента и затем возвращается сумма вычислений:

public static class Algorithm

{

public delegate TSummary Action(TInput t, TSummary u);

public static TSummary Accumulate(IEnumerable

coll, Action action)

{

TSummary sum = default(TSummary);

foreach (TInput input Обобщенные делегаты in coll)

{

sum = action(input, sum);

}

return sum;

}

}

Метод Accumulate( ) может быть вызван методом Main с применением анонимного метода, который определяет баланс счета, в качестве второго параметра:

decimal amount = Algorithm.Accumulate(acounts, delegate(Account acc, decimal d)

{ return acc.Balance + d;});

Если в дополнение к Account балансы могут понадобиться более одного раза, то можно перенести функциональность в отдельный метод —
AccountAdder( ) класса Algorithm:

public static decimal AccountAdder(Account acc, decimal d)

{

return acc.Balance + d;

}

Тогда его можно использовать с методом Accumulate( ) в методе Main:

decimal amount = Algorithm.Accumulate(acounts, Algorithm.AccountAdder);

Метод, на который указывает делегат Action, может реализовывать Обобщенные делегаты другую логику; например, вместо сложения может применять умножение.

Применив метод AccumulateIf( ), можно сделать метод Accumulate( ) более гибким. В методе AccumulateIf( ) добавим дополнительный параметр типа Predicate. Делегат Predicate ссылается на метод, который должен быть вызван для проверки счета, участвующего в накоплении. В цикле foreach метод Action будет вызван только в том случае, если предикат match возвратит true:

public static TSummary AccumulateIf

(IEnumerable coll,

Action action,

Predicate match)

{

TSummary sum = default(TSummary);

foreach (TInput input in coll)

{

if (match(input))

{

sum = action(input, sum);

}

}

return sum;

}

Вызов метода AccumulateIf( ) может иметь реализацию накопления и реализацию предиката. Следующим образом можно Обобщенные делегаты выполнить накопление только тех счетов, чей баланс превышает 200000:

decimal amount = Algorithm.AccumulateIf(

acounts,

delegate(Account acc, decimal d) { return acc.Balance + d; },

delegate(Account acc){return acc.Balance > 200000 ? true : false;});

Результаты работы программы с использованием
метода AccumulateIf( ) приведен на рис. 7.9

Рис. 7.9. Результаты работы программы с использованием
метода AccumulateIf( )

В этой лекции были рассмотрены обобщения. Благодаря механизму обобщений, можно создавать классы и методы, независимые от типов. Интерфейсы, структуры и делегаты также могут быть созданы в обобщенной манере. Обобщения позволяют применить новый стиль программирования. Было показано, как алгоритмы, в частности, действия и предикаты, могут быть реализованы для работы с различными классами Обобщенные делегаты — и все это с обеспечением безопасности типов. Обобщенные делегаты позволяют отделить алгоритмы от коллекций.

Основное назначение обобщений — классы коллекций. Среда .NET расширена пространством имен System.Collections.Generic, включающим обобщенные версии классов коллекций из пространства имен
System.Collections. Мы рассмотрели использование нескольких обобщенных классов коллекций, таких как List, Queue.




documentagctumr.html
documentagcubwz.html
documentagcujhh.html
documentagcuqrp.html
documentagcuybx.html
Документ Обобщенные делегаты