What is a predicate?
Predicates are simply generic Delegates which have been defined in .NET 2.0 in the following way:
Public delegate bool Predicate<T> (T obj)
The idea is that predicates receive a certain object and return true if it answers certain criteria. This doesn’t too exciting, but .NET 2.0 framework allows these predicates to be used with arrays and lists.
Suppose we have a array of random integers and we want to determine all odd numbers. We can define the following function:
Private bool IsOdd(int num) { return (num % 2 == 0); }
Then you can search the array or even return an array which includes all of the objects answering the chosen criterion, by using the static methods Array.Find or Array.FindAll. For instance, if our Array is called array, we can determine odd numbers in it thus:
int [] results = Array.FindAll (array, IsOdd) ;
Predicates in Lists:
This one works for the generic List also. For instance, if we define a generic list of numbers:
List<int> list = new List<int> () ;
We can return all of the odd numbers in the list into a new list this way:
List<int> result = list.FindAll (IsOdd) ;
Note that methods which use predicates on arrays are static methods of the Array class, while methods which use predicates on lists are activated from the list’s specific Instance. Which is not very important, but worth knowing just in case.
What else can you do with predicates?
Other arrays and list methods which use predicates are: FindLast, FindAll, Find, Exists, and TrueForAll. For lists, there is another method which uses predicates and which is called RemoveAll. For arrays, it’s also possible to use predicates to return object indexes using the methods FindIndex and FindLastIndex.
Converter and Action:
Two methods offer a slight twist to the whole issue of predicates, and they are mentioned here because they are really, really useful. The first is the method ForEach. It doesn’t use predicate-type delegates, but Action delegates. Its definition is:
public delegate void Action<T> (T obj)
This method performs actions on every object in a set or list: for example, prints to any output.
But the truly wonderful method is ConvertAll – a method bound to be especially useful to all the analysts out there who ever wanted to convert, the easy way, sets of chars into sets of bytes. Use this method for one kind of generic list, and you get another kind. You will simply have to provide the method ConvertAll with a Converter method. The definition of Converter is this:
public delegate TOutput Converter<TInput, TOutput> (TInput input)
That is, if we have a list of ints, and we want to convert it into a list of doubles, we can create the following method:
Public double IntToDouble (int num) { return (double)num; }
And then take a list of ints and perform:
List<double> result = list.ConvertAll<double> (IntToDouble) ;
We can use this method for arrays as well, but we will need to specify the type of input array and the type of output, because we operate the method from a static class because the method is static – and it therefore has no information about our initial array. For example, if we have a array of ints called arr:
double [ ] result = Array.ConvertAll<int, double> (arr, IntToDouble) ;
Naturally, you don’t have to be content with simple casting. You can use, say, the method of conversion to return a array which includes the square root of every member in the original array. Like ForEach, ConvertAll is useful to perform actions on especially large sets.
Predicates and Actions are the little things which can safe precious development time and make the code more readable.
Thanks to Idan Zairman for this blog |