multi-cast delegates and Predicate<T>

Since Predicate<T> that is used for finding stuff in a generics list is in fact a multi-cast delegate, I thought it might be possible to chain several Predicates to simplify multiple requirements for the elements returned.

Consider the following code:

Predicate<int> greaterThan5 = delegate(int x) { return x > 5; };
Predicate<int> lessThan10 = delegate(int x) { return x < 10; };

It would be cool if it would be possible to chain them, by doing a simple:

Predicate<int> combined = lessThan10 + greaterThan5;

And then:

List<int> resulting = allInts.FindAll(combined);

Unfortunately it dosen't work, or more precicely, it is only the last delegate that gets invoked.

It seems like MS did not envision people wanting to use multi-cast delegates for their predicates, and when looking at the List.FindAll implementation, its very clear, since it only invokes the delegate as it were a single cast one:

public List<T> FindAll(Predicate<T> match)
{
    if (match == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
    }
    List<T> list = new List<T>();
    for (int i = 0; i < this._size; i++)
    {
        if (match(this._items[i]))
        {
            list.Add(this._items[i]);
        }
    }
    return list;
}


So unfortunately you still need to do the old fashion way:

List<int> resulting = allInts.FindAll(lessThan10).FindAll(greaterThan5);

Lets hope they change it in c# 3.0

Comments (2) -

Your "old fashion way" could save an iteration on the collection:

List<int> resulting = allInts.FindAll(delegate(int x){ return lessThan10(x) && greaterThan5(x);});

But you are right it definetely should be implemented in FindAll, and to make it even more complicated. It is not possible to inherit from Predicate<T> if you could that you could overload the + operator and combine the delegates into the delegate shown above.

Your comment are naturally true.

The only reason for having two delegates in my example, is that the delegates might be a lot more advanced, and would as such not neccesarily be feasible for combination.

Another place where it would not be feasible is the List.ForEach where the Predicate's might not even do something remotely the same.

Comments are closed