Action<T>
is a
generic type for a delegate to a function that
returns void
, and takes a single
parameter of some type T
. We used a
generic type before: the List<T>
(List-of-T) where T
represents the type
of the objects that can be added to the list. In this case, we have an
Action-of-T where T
represents the type
of the parameter for the function.
So, instead of declaring our own delegate:
delegate void DocumentProcess( Document doc );
we could just use an Action<>
like this:
Action<Document>
A quick warning: although these are functionally equivalent, you
cannot use an Action<Document>
polymorphically as a DocumentProcess
—they are, of course, different
classes under the covers.
We’re choosing between an implementation that uses a type we’re declaring ourselves, or one supplied by the framework. Although there are sometimes good reasons for going your own way, it is usually best to take advantage of library code if it is an exact match for your requirement.
So, we can delete our own delegate definition, and update our
DocumentProcessor
to use an Action<Document>
instead, as shown in
Example 5-12.
Compile and run, and you’ll see that we still get our expected output.
One way we might be able to do this is to provide a means of supplying an optional “check” function corresponding to each “action” function. We could then iterate all of the check functions first (they are supposed to be quick), and look at their return values. If any fail, we can give up (see Figure 5-3).
We could implement that by rewriting our DocumentProcessor
as shown in Example 5-13.
There are quite a few new things to look at here.
First, we declared a new class inside our
DocumentProcessor
definition, rather
than in the namespace scope. We call this a nested class.
We removed the public property for our list of processes, and
replaced it with a pair of AddProcess
method
overloads. These allow us to add processes to the sequence; one takes both
the action and the check, and the other is a convenience overload that
allows us to pass the action only.
What type is a Check
? We need a
delegate to a method that returns a Boolean
and takes a Document
:
delegate bool Check(Document doc);
We call this type of “check” method a predicate: a function that operates on
a set of parameters and returns either true
or false
for a given input. As you might expect, given the way things have been
going so far, this is a sufficiently useful idea for it to appear in the
framework (again, as of .NET 3.5).