Comments
Richard Davies wrote: The UK has a good crop of technology pioneers in cloud computing - for example ElasticHosts, FlexiScale, Flexiant, OnApp - and also some strong government initiatives such as G-Cloud. We will have to see whether this kind of technical leadership converts into swift mass-market adoption or not.
Cloud Computing
Conference & Expo
November 2-4, 2009 NYC
Register Today and SAVE !..
SYS-CON.TV
Today's Top SOA Links


Harnessing the Power of Predicates in .NET 2.0
Generics, generic collections, and delegates

Predicate is a new feature introduced in .NET 2.0 in conjunction with Generic collections. Generics are also new in .NET 2.0; Generic collections are by nature strong-typed. What that means is that if we declare a generic list of Address objects, we can only insert an Address type of object. If you try to insert an object that's not an Address type of object or a derived class of it, you'd get a compilation error. So using Generic collections ensures type-safety. In .NET 1.1, we'd have to use an ArrayList (which is a list of "object"-type items). There are two imminent drawbacks to using an ArrayList: first, it doesn't offer type-safety (you could insert heterogeneous type of objects); second, when retrieving items from the list, you have to type-cast the objects, and if the type doesn't match, you could be greeted with an InvalidCastException. With a generic list, both of these hurdles could be avoided. So, the rule of the thumb is that, if you're using .NET 2.0, use a Generic collection such as List<T> or Array<T>.

Now that we've realized the importance of using a strong-typed collection, let's concentrate on the main topic of this article - Predicates. Whenever we have a collection, inevitably there's a need to search for items in the collection that satisfy a specific criterion. That's where Predicates come into play. Predicates help to write elegant code by avoiding the crud "for each" code that's needed to loop through the collection searching for the items that satisfy a particular criterion.

Let's take a simple example. Let's consider that we have a Person class that contains a list of Address objects and a list of Phone objects. Let's further assume that there's one "primary" address and phone for a Person (indicated by a bool Property called IsPrimary in Address and Phone classes). Given a Person object, if you have to find the Primary address, you'd generally have to loop through the list of Address objects until you find it; alternatively, you could define a Predicate that defines the criterion (check if "primary"), and you could search for one with just a line of code. Let's see both these approaches in code (see Listing 1).

As you can see, there's less code with the second approach. Notice how we pass the name of the function to the Find method of Addresses. The function, SearchPrimaryAddress, could actually be implemented in another class; for convenience, we have implemented in the same class (Person). Note the signature of this function - it takes an input parameter of Address (that's the same type of object as contained in the Addresses collection) and the return type of bool. The specialty of this function is that it defines a criterion or condition (that in this case is addr.IsPrimary), which is run against each item in the list until the desired result is met.

Predicate is always defined with respect to a strong-typed collection. Its signature consists of the return value of bool and an input parameter of the type of object that's present in the collection. The function itself contains the logic to return a true if the object that's passed as the input satisfies the criterion defined in the function. This function is evaluated recursively until the desired result is met.

Generic List<T> has several functions that take a Predicate - Exists, Find, FindAll, FindFirst, FindLast. You don't have to write separate Predicates for each of these functions. In the example earlier, if you have to find if a Person has a primary Address set in its property Addresses, we'd just have to call Exists function, passing to it the Predicate, SearchPrimaryAddress as shown in Listing 2.

In the examples given so far, the criterion was implicitly tied to the function; i.e., we didn't pass the criteria to the function. Let's say you want to find all Address objects that have the Property State as "Illinois," you could write a Predicate that could search for the criteria where the State of the Address is "Illinois"; but what do you do if you want to find all addresses in "Iowa," or in other states? You don't want to write 50 different Predicates to find addresses in 50 states; instead, you have to define a class that has the member function that serves as the Predicate and a class Property that you can set, prior to calling the Predicate that defines the values for the condition. Let's illustrate this with the example in Listing 3. Now, to find all the addresses in "Illinois" for a given person (instance of Person), you'd have to do as shown in Listing 4.

Let's say that you want to include "City" in the search too. You'd have to add this as a Property in the Predicate class (SearchStatePredicate) and initialize it prior to the Search function call.

Let's extend this to another example. Let's say you'd like to display all the persons in an organization in a paginated grid, categorized alphabetically. The letters A through Z would be displayed on the footer of the grid; when the user clicks on any letter, you have to show the users whose last name starts with the letter selected.

Assume that you have the list of Persons for the organization available to you in a Generic List. To find the list of Person objects whose names start with the letter selected, we'd first have to define a Predicate class that has the Properties required to define the conditions for the criterion and a member function that can serve as the Predicate (see Listing 5).

Let's say you have all the persons in an organization in a Generic List called everyone. To find the list of persons whose last names start with a letter defined by the variable alpha, you could follow Listing 6.

Let's see how we could use FindFirst and FindLast functions of a list; to ensure the veracity of these functions, we first have to sort the items in the list. Sorting is a breeze as you can see from the code in Listing 7.

The function SortByLastName could be defined in the Person class or any other class as a static function. SortByLastName is the name of the function that would be called recursively to sort the list; similar to the Predicate, this delegate has a special signature that takes two input arguments of objects of the same type as those that are contained in the collection and a return type of int. Once the list has been sorted, we could call FindFirst and FindLast as shown in Listing 8.

As you might infer, by writing the Predicate once we could use it in a number of ways without having to write any additional code. Understanding Predicates may take a little while, but, once you write one on your own, you'll grasp it. Predicates are very useful since it not only ensures code reuse but also elegance in the code. Predicates work only with strong-typed collections and hence ensure type-safety. Some programmers prefer to use anonymous delegates when writing Predicates; I generally avoid that because it might be hard to understand and difficult to maintain.

To sum up, here's my recommendation: Whenever you have to use a collection, it's better to use a strong-typed collection like List<T> over an ArrayList. We've already seen the advantages of using a strong-typed collection over a weakly typed collection. When using a collection, we'd inevitably have to search for items contained in it that satisfy some criteria. Predicates are essential functions that define the criteria; it would pay off to learn to use Predicates. Unleash the power of Predicates to write elegant code.

About Srinivas K. Surampalli
Srinivas K. Surampalli alias Kal is a senior consultant at Magenic Technologies. He has over a decade of experience in delivering innovative technology solutions to businesses using Microsoft Technologies. He is a MCSD for Microsoft.NET and Microsoft Visual Studio 6.0. When not working, Kal enjoys playing with his two children Avyay and Anagha.

In order to post a comment you need to be registered and logged in.

Register | Sign-in

Reader Feedback: Page 1 of 1

Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021

SYS-CON Featured Whitepapers
ADS BY GOOGLE