How Can I Use a LINQ Lambda Expression With Distinct()?

Contrary to what most of other LINQ extension methods provide when dealing with collections of objects, the Distinct() method takes in an object of a class that implements IEqualityComparer<T> interface. When selecting distinct objects, you probably are thinking about having code like this:

var distinctObjects = collection.Distinct((object1, object2) => object1.Id == object2.Id);

However, this is not an option in System.Linq assembly.
There, of course, are a number of ways to select distinct objects in your code. The lambda expression above is one way to provide a function for it and will certainly vary on how you define objects to be equal. It would still be nice to be able to do it this way rather than implementing a whole new class.

First of all, if you are not familiar with extension methods, take a peek at how to implement extension methods. Now, let’s look at how we can implement an extension method as in above code.

To be able to have a lambda expression like above, the method signature will have to have two objects of the same type and a boolean result which will return whether the two objects are equal and which will be used to select distinct values from the collection:

public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source, Func<T, T, bool> equalityFunction) where T : class

Notice that we are using T as a type identifier and have a where T : class statement indicating that T is an class type. We also specify that our Distinct() method is going to be an extension method for any class T that implements IEnumerable. We then specify that the argument to this method is going to be a LINQ function that takes two objects of class T and returns a boolean.

The rest is easy – you can now pass a lambda expression as the Func(T, T, bool) and call equalityFunction just like any other method. So all that is left is simply selecting distinct objects:

var result = new List<T>();
foreach (var item in
	from item in source 
		from resultItem in result.Where(resultItem => !equalityFunction(resultItem, item)) select item)
{
	result.Add(item);
}			
return result;

In the above code, the inner from will check that the object does not already exist in result collection by calling the equalityFunction(). If that is the case, the outer from statement will result in only distinct objects that will be added to the result collection.

I hope this is helpful to someone and feel free to comment and ask questions.

This entry was posted in C#, LINQ and tagged , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *