Monthly Archives: July 2009

LINQ: Distinct method

Ah the beauty of LINQ. I previously did a post on How to use Lambda Expressions and if you aren’t sure now how to use them, is the time to check it out. I have decided to have a good look at the Methods available to IEnumerable collections and first on the list the DISTINCT method.

The Boring Standard Method:

The Distinct method removes any duplicate entries in a collection without you needing to do much work, the same as the DISTINCT keyword inT-SQL. Here is the basic and standard use that is really not difficult to understand.

string[] names = new string[] { "Peter", "Paul", "Mary", "Peter", "Paul", "Mary", "Janet" };

foreach (string _name in names.Distinct())
{
Console.WriteLine(_name);
}

So like I said, easy enough, we have a string array with names and by using the .Distinct method we remove any duplicates from the resultset that is returned. Now comes the real fun!

Custom Distinct Implementation:

Since the advent of generics, most of us have been creating strongly typed lists of data. Plain example would be a list of our customer UserClass.

public class Users
{
public int ID {get; set;}
public string Name {get; set;}
public int AwesomeScore {get; set;}
}

// Create and populate new list of Users
List<Users> failBoyUsers = new List<Users>();
failBoyUsers.Add(new Users { AwesomeScore = 7, Name = "FailBoy", ID = 1 });
failBoyUsers.Add(new Users { AwesomeScore = 10, Name = "Rathlan", ID = 2 });
failBoyUsers.Add(new Users { AwesomeScore = 10, Name = "Rathlan", ID = 2 });
failBoyUsers.Add(new Users { AwesomeScore = 7, Name = "Joe", ID = 3 });
failBoyUsers.Add(new Users { AwesomeScore = 7, Name = "Joe", ID = 3 });
failBoyUsers.Add(new Users { AwesomeScore = 7, Name = "Joe", ID = 3 });
failBoyUsers.Add(new Users { AwesomeScore = 1, Name = "newbie", ID = 4 });

This would then give us a “strongly typed Array” of our User class. If we now had to call the .Distinct function on the collection it wouldn’t work! Thats because the CLR does not know what to evaluate to decide whether an entry is unique or a duplicate so it returns all the items including the duplicates. The Distinct method accepts an overload paramter, this object must implement the IEqualityComparer interface. So we declare a new class and implement IEqualityComparer as follows:

public class AwesomeComparer : IEqualityComparer<Users>
{
public bool Equals(Users x, Users y)
{
if (x == null || y == null)
return false;
else
return (x.Name.ToLower() == y.Name.ToLower() &&
x.AwesomeScore == y.AwesomeScore &&
x.ID == y.ID);
}

public int GetHashCode(Users obj)
{
return obj.Name.GetHashCode();
}
}

so what we do in the Equals Method is define what we feel a duplicate of our custom class looks like. We also implement the GetHashCode method to return the hash of the “primary field”. This will usually be the Primary Key that you class will be based on. Then we implement our Distinct method, we do so as follows:

AwesomeComparer awesomeComparer = new AwesomeComparer();

foreach (Users usr in failBoyUsers.Distinct(awesomeComparer))
{
Console.WriteLine(usr.ID.ToString() + " - " + usr.Name + " - " + usr.AwesomeScore.ToString());
}

And that will only return Distinct values from our custom class! I hope this helps someone at some stage as I never knew about this myself and stumbled onto it. Drop me a comment if you think I suck or if my some margain of luck I managed to produce some bug free code, I am after FailBoy for a reason :P

How to use Lambda Expressions

Until I recently started working at Chase Software I hadn’t really dived to deep into the C# 3.0 features. I really wish I had though because man it would’ve cut down so much code at my previous job. A colleague of mine has taught me so much that I am now looking a lot deeper into C# 3 features. Just in time before C# 4.0 is released! One of the first things I learned to get the hang of is Lambda expressions. Lambdas are inline expressions. These expressions are mainly used in conjunction with LiNQ and thus mostly on IQueryable and IEnumerable collections. Here is an example on how it can cut a lot of code out of you work.

Assume we have a basic class that contains a Name, ID and AwesomeScore for Users.

public class Users
{
public int ID {get; set;}
public string Name {get; set;}
public int AwesomeScore {get; set;}
}

So as you can see there’s nothing difficult about that. Its a basic class definition. So lets create a basic console application and fill a List of Users so we can work with that:

public static void Main(string[] args)
{
// Create and populate new list of Users
List<Users> failBoyUsers = new List<Users>();
failBoyUsers.Add(new Users { AwesomeScore = 7, Name = "FailBoy", ID = 1 });
failBoyUsers.Add(new Users { AwesomeScore = 10, Name = "Rathlan", ID = 2 });
failBoyUsers.Add(new Users { AwesomeScore = 9, Name = "Joe", ID = 3 });
failBoyUsers.Add(new Users { AwesomeScore = 1, Name = "newbie", ID = 4 });
}

So here we create a Generic List Collection of Users. So our failBoyUsers collection now contains 4 users with varying scores. Now, originally before the wonders of learning how to use Lambda’s, I would’ve done the following to return the users with an AwesomeScore of 8 or over:

public static List GetAwesomestPeople(List<Users> usersToSort)
{
List<Users> returnList = new List<Users>();

foreach (Users userItem in usersToSort)
{
if (userItem.AwesomeScore >= 8 )
{
returnList.Add(userItem);
}
}

return returnList;
}

So yeah, that was me, FailBoy being very intelligent. Now, that same functionality using Lambda’s.

public static IQueryable GetAwesomestPeopleLAMBDA(IQueryable usersToSort)
{
return usersToSort.Where(user => user.AwesomeScore >= 8).AsQueryable();
}

Thats right! Using Lambda’s its a single line. So lets look at that line, I pass in the usersToSort as IQueryable instead of the List. Converting from the List to IQueryable is as easy as passing the List parameter in and simply adding .AsQueryable() to the end of the parameter name! So it would be called as :

IQueryable awesomeOkes = GetAwesomestPeopleLAMBDA(failBoyUsers.AsQueryable());

Then I use the .Where() method which is an extension method on the IQueryable collection class and as such on the List<> class since List<> inherits from IEnumerable and IEnumerable inherits from IQueryable. The fun comes in where I pass the argument into the .Where() method.

user => user.AwesomeScore >= 8

Here I am declaring a new variable called user. The variable is an instance of the Collection we want to sort, in this case usersToSort. the “=>” is what is referred to as the Lambda operator. After the Lambda operator we specify our condition. In this as we only want the users with an AwesomeScore of 8 or higher. I then append the

.AsQueryable()

because we want to return the resultset as an IQueryable Collection of Users.

Using Lambda’s I’m condensed 9 lines of code into 1 line of code. And the less you need to code, the more time you save! I hope this is helpful to you! I’ve included the full code below.

FailBoy