After reading post about List Predicates at the very informative BCL Team Blog, I did some research to see how flexible the predicates actually are.
I found out that none of the methods taking a Predicate as a parameter support chained delegates (more info about combining delegates), only the delegate added last to the chain is executed in my experience.
Example:
// Prepare collection List<int> list = new List<int>( new int[]{1,2,3,4,5,6} ); // function to determine if the int is less than 5 Predicate<int> LT5 = delegate(int x){ return x < 5; }; // function to determine if the int is greater than 2 Predicate<int> GT2 = delegate(int x){ return x > 2; }; // combine the predicates: // return true for 2 < x < 5 Predicate<int> GT2LT5 = null; GT2LT5 += GT2; GT2LT5 += LT5; List<int> result = list.FindAll(GT2LT5); // writes 1,2,3,4 result.ForEach( delegate( int x) { Console.WriteLine( x ); });
A work around would be to use the second delegate on the result collection after calling the FindAll method with the first delegate, but this doesn't scale with more delegates.
// first use the first delegate List<int> intermediate = list.FindAll(LT5); // now use the second delegate on the intermediate result List<int> result = intermediate.FindAll(GT2); // writes 3,4 result.ForEach( delegate( int x) { Console.WriteLine( x ); });
Another solution is to enumerate through the collection and call each delegate in the invocation list.
// Prepare collection List<int> list = new List<int>( new int[]{1,2,3,4,5,6} ); // function to determine if the int is less than 5 Predicate<int> LT5 = delegate(int x){ return x < 5; }; // function to determine if the int is greater than 2 Predicate<int> GT2 = delegate(int x){ return x > 2; }; // combine the predicates: // return true for 2 < x < 5 Predicate<int> GT2LT5 = null; GT2LT5 += GT2; GT2LT5 += LT5; // prepare result List<int> result = new List<int>(); foreach(int i in list ){ bool valid = true; // GetInvocationList returns all combined delegates foreach( Predicate<int> match in GT2LT5.GetInvocationList() ){ valid = valid & match(i); } if( valid ){ result.Add(i); } } // writes 3,4 result.ForEach( delegate( int x) { Console.WriteLine( x ); });
Both solutions are less than ideal.