Reshef’s tip of the day

.net development tips

Creative operator overloading

This post is based on two facts about C#:

1) An operator is a method. It is a static method that receives 1 or 2 parameters, depends on the operator and returns a value.

2) The return value can be anything you want it to be. Usually the operator == returns a boolean, but it can return any other data type.

The example I will show is about searching for a value in a generic list.

The .net generic list has a method called FindIndex with the following signature:

public int FindIndex(Predicate match);

Predicate is a delegate that receives a parameter of type T for evaluation and returns a boolean in case the that there is a match according to the logic defined by the predicate. This works like This:

int indexOfUserToLookFor = usersList.FindIndex(delegate(User u)
{
    return u.FirstName == userToLookFor.FirstName &&
        u.LastName == userToLookFor.LastName;
});

where usersList is defined as List and User is a class. The code above is not so elegant or readable. Having something like:

int indexOfUserToLookFor =
    usersList.FindIndex(Where.User == userToLookFor);

would be much nicer and certainly more readable.

In order to enable such syntax, the two fact about operator overloading mentioned above come to play. The code:

public class UserQuery
{
    public static Predicate<User> operator ==
        (UserQuery ignored, User other)
    {
        return new Predicate<User>(delegate(User u)
        {
            return u.FirstName == other.FirstName &&
                u.LastName == other.LastName;
        });
    }
    …
}

does the trick. What this code means, is that when the operator == is used for object of type UserQuery (left hand side) and User (right hand side), return a Predicate that contains the logic to match a user. Pay attention that the UserQuery parameter is named ignored since it is indeed, ignored. The predicate that is returned is the same as the predicate in the first FindIndex snippet therefore the functionality is the same.

The Where in the phrase ‘Where.User == userToLookFor’ is just for nicer syntax. It is implemented simply as:

public static class Where
{
    public static UserQuery User
    {
        get
        {
            return new User.UserQuery();
        }
    }
}

This post was inspired by the code generated using the NHibernate Query Generator which uses this technic extensively. For an example of code by the NQG look here.

The complete code example for this post can be downloaded here

Tags: ,

Leave a Reply

Jajah is the VoIP player that brought you web-activated telephony.