Labels

Monday, July 2, 2007

The "Predicate Delegate"

 

A delegate is like a function pointer. The Predicate delegate is a Generic method which takes an object of type T as a parameter. It returns true or false, indicating whether or not the object of type T satisfies the condition it tests. The System.Array and System.Collections.Generic.List classes of the .NET Framework 2.0 each provide a number of methods, such as Find, FindAll, and FindLast, that let you avoid writing code to loop through every element of an array or list to find the one or more items you're looking for. You get the ability to "walk" an entire data structure, determining whether each item meets a set of criteria, without having to write the boilerplate code to loop through each row manually.

 

Let's say, for example, I have an array of numbers and I want to find all of the numbers which are odd. The obvious way is simply to loop through them checking each number for its "oddness" and adding it to an output array, like so:

 

 int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

       int[] odds = GetOdds(numbers);

 

       private static int[] GetOdds(int[] numbers)

       {

           int[] odds = new int[numbers.Length];

           int counter = 0;

           for (int i = 0; i < numbers.Length; i++)

           {

               if ((numbers[i] % 2) != 0)

               {

                   // Found an odd!

                   odds[counter++] = numbers[i];

               }

           }

           return odds;

       }

 

This works...but it's a little ugly. Majority of our method seems to be just overhead to support the output array, looping through the input array, etc.  The core logic itself is actually constrained to just one line:

 

  if ((numbers[i] % 2) != 0)

 

It seems like that there should be a cleaner way to do this and, there is using Predicates, we can actually just write this little line of code into a stand alone method and reference it directly from the Array.FindXXX() methods. 

 

        int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };       

        int[] odds = Array.FindAll<int>(numbers, IsOdd);

        private static bool IsOdd(int number)

        {

            return ((number % 2) != 0);

        }

 

Now the only thing that we have to worry about is our core logic, .NET takes care of all of the additional overhead for us!

 

We can even reference it inline using anonymous delegates!

 

  int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        int[] odds = Array.FindAll<int>(numbers,

            delegate(int number)

            {

                return ((number % 2) != 0);

            });

 

We can use this technique for any of the Find methods of the Array class (Find, FindAll, FindIndex, FindLast, and FindLastIndex) as well as the Exists method to see if any objects matching our condition exist in the array.

 

Hopefully this will help clean up some of those annoying routines you have scattered through your code that are just in place solely to get what you need from an array, check if an array has what you need, or just pull out a certain type of object from your array.

 

 

Thanks & Regards,

Arun Manglick

SMTS || Microsoft Technology Practice || Bridgestone - Tyre Link || Persistent Systems || 3023-6258

 

DISCLAIMER ========== This e-mail may contain privileged and confidential information which is the property of Persistent Systems Pvt. Ltd. It is intended only for the use of the individual or entity to which it is addressed. If you are not the intended recipient, you are not authorized to read, retain, copy, print, distribute or use this message. If you have received this communication in error, please notify the sender and delete all copies of this message. Persistent Systems Pvt. Ltd. does not accept any liability for virus infected mails.

No comments:

Post a Comment