Implementing Methods Called by Delegates
The method Accumulate() is changed to have two generic types.
TInput is the type of the objects that
are accumulated, and TSummary is the
returned type. The first parameter of Accumulate is the interface IEnumerable<T>, as it was before. The second
parameter requires the Action delegate
to reference a method that is invoked to accumulate all
balances.
With the implementation, the method referenced by
the Action delegate is now invoked for
every element, and then the sum of the calculation is returned:
The method Accumulate
can be invoked using an anonymous method that specifies that the
balance of the account should be added to the second parameter:
If the addition of Account balances is needed more than once, it is
useful to move the functionality into a separate method,
AccountAdder():
And use the AccountAdder
method with the Accumulate method:
The method referenced by the Action delegate can implement any logic; for
example, a multiplication could be done instead of a summation.
The Accumulate() method
is made more flexible with the AccumulateIf() method. With AccumulateIf(), an additional parameter of type
Predicate<T> is used. The delegate
Predicate<T> references the method
that will be invoked to check whether the account should be part of
the accumulation. In the foreach
statement, the action method will be
invoked only if the predicate match
returns true:
Calling the method AccumulateIf() can have an implementation for the
accumulation and an implementation for the predicate. Here, only
the accounts with a balance higher than 2000 are accumulated:
Using Generic Delegates with the Array Class
Chapter 5, “Arrays,” demonstrated
different sort techniques with the Array
class by using the IComparable and
IComparer interfaces. Starting with .NET
2.0, some methods of the Array class use
generic delegate types as parameters. The following table shows
these methods, the generic type and the functionality.
Let’s get into how these methods can be used.
The Sort() method
accepts this delegate as parameter:
This way, it is possible to sort the array by using
an anonymous delegate passing two Person
objects. With an array of Person
objects, parameter T is of type
Person:
The Array.ForEach()
method accepts an Action<T>
delegate as parameter to invoke the action for every element of the
array:
This way, you can write every person to the console
by passing the address of the method Console .WriteLine. One
overload of the WriteLine() method
accepts the Object class as parameter
type. Because Person derives from
Object, this fits with a Person array:
The result of the ForEach() statement writes every person of the
collection referenced by the persons variable to the console:
If more control is needed, you can pass an
anonymous method that fits the parameter defined by the
delegate:
Here, the result is the last name written to the
console:
The Array.FindAll()
method requires the Predicate<T>
delegate:
The Array.FindAll()
method invokes the predicate for every element in the array and
returns a new array where the predicate returns true for the element. In the example, true is returned for all Person objects where the Lastname starts with the string “S”:
Iterating through the returned collection
sPersons to write it to the console
gives this result:
The Array.ConvertAll()
method used the generic delegate Converter with two generic types. The first generic
type TInput is the input parameter, the
second generic type TOutput is the
return type:
The ConvertAll() method
is very useful if an array of one type should be converted to an
array of another type. Following is a Racer class that is unrelated to the Person class. The Person
class has a Firstname and a Lastname property, while the Racer class defines for the name of the racer just
one property Name:
Using Array.ConvertAll()
you can easily convert the person array persons to a Racer array.
The delegate is invoked for every Person
element. In the anonymous method implementation for every person, a
new Racer object is created, and the
firstname and lastname are passed concatenated to the constructor,
which accepts a string. The result is an array of Racer objects: