.comment-link {margin-left:.6em;}
Books & Articles I wrote.

Tuesday, January 24, 2006

 

Filtering Generic Lists

I have to say that the more i work with Generics, the more i think they're the best thing to be added to C# 2.0. Recently I had a List<> of Groups and wanted to discover whether a certain User existed in any of those groups. There are a number of ways to do this, but traditionally you may iterate over the groups using foreach and then iterate acorss the members, check whether any UserID of a member matched the UserID of the User entity that was passed and store any matches. You may write a custom collection and add a method to do this for you, but all in all, performing searching on objects was a bit of a pain.

Generics makes this a whole lot easer. Using Predicates and delagates which can be used to perform custom searches on your generic collections and work without writing custom classes of iterations and so on.

So, back to my problem. Let's first wite a GroupFilter class that will be used in the Predicate for our filtering. You pass the ID of the user you are searching for in the constuctor of this class. I then define a method that is delegated to by this Predicate to evaluate whether our test condition is true. As you call a method such as Exists() on a generic collection, with this class as the Predicate, each item in the List is passed in context to the delegated method. In my case i have a List and so each User in the list will be passed to this method.

public class GroupFilter
{
int _userid;


public GroupFilter(int userid)
{
_userid = userid;
}

public bool HasUser(User user)
{
return user.UserID == _userid;
}
}

There are a number of ways we can proivde access to this from a software client perspective, but i prefer to wrap these into common queries and provide a simple interface to it and in my case i just define a ContainsUser() method which takes the id of the user to search for. A Predicate is then defined and an instance of the GroupFilter class is constructed using the id of the user we are going to search for. Finally the delegate is set to a new instance of the Predicate which points to the HasUser method, saying that when this Predicate is used, the HasSer method will be delegates to provide the result. The Predicate can then be used with a bunch of methods,but in my case i just want to test whether the user exists in the Members collection of the Group and so i pass it to the Exists() method, which returns true if the user exists in the group.

public bool ContainsUser(int memberid)
{
//create an instance of the hasuser predicate
Predicate hasUser;

//now instantiate a group filter for members
GroupFilter filter = new GroupFilter(memberid);

//set up the delagate for the list filter
hasUser = new Predicate(filter.HasUser);

return this.Members.Exists(hasUser);
}

As i said, fantastic stuff and I intend to use them quite a bit more. I hope sharing this will help as finding info that was more than string evaluation was a bit of a pain.


This page is powered by Blogger. Isn't yours?

Weblog Commenting and Trackback by HaloScan.com