Translate

Monday, January 14, 2013

LINQ select distinct not working (LINQ select distinct does not work)

LINQ select distinct works as expected if you are returning a List of anonymous types or a List of a primitive type. But it seems not to work if you are returning a List of a class. The way to fix that is to implement IEqualitycomparer<T> interface and pass in an instance of that implementation to the the Distinct method.  Its easier to understand this with a simple example.

The aim in the code below is to differentiate people based on their Social Security Number.

Code where select distinct does not work

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace IEqualityComparer

{
    class Program
    {
        static void Main(string[] args)
        {
 
            var people = new List<Person>();
 
            people.Add(new Person { SocialSecurityNumber = "A", Name = "Pam" });
            people.Add(new Person { SocialSecurityNumber = "B", Name = "John" });
            people.Add(new Person { SocialSecurityNumber = "C", Name = "Susan" });
            people.Add(new Person { SocialSecurityNumber = "D", Name = "Tom" });
            people.Add(new Person { SocialSecurityNumber = "A", Name = "Pam" });//THIS RECORD IS REPEATED
 
            var distinctPeople = (from p in people select p).Distinct();
 
            foreach (var person in distinctPeople)
            {
                Console.WriteLine(person.Name);//PAM GETS PRINTED TWICE, HENCE SELECT DISTINCT DOESNOT WORK
            }
 
        }
    }
 
    public class Person
    {
        public string SocialSecurityNumber { getset; }
        public string Name { getset; }
 
    }
}

Output:
Pam
John
Susan
Tom
Pam
Press any key to continue . . .




Code where select distinct works

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace IEqualityComparer
{
    class Program
    {
        static void Main(string[] args)
        {
 
            var people = new List<Person>();
 
            people.Add(new Person { SocialSecurityNumber = "A", Name = "Pam" });
            people.Add(new Person { SocialSecurityNumber = "B", Name = "John" });
            people.Add(new Person { SocialSecurityNumber = "C", Name = "Susan" });
            people.Add(new Person { SocialSecurityNumber = "D", Name = "Tom" });
            people.Add(new Person { SocialSecurityNumber = "A", Name = "Pam" });
 
            var distinctPeople = (from p in people select p).Distinct(new PersonComparer());//Note that an implementation of IEqualityComparer<Person> is passed in
 
            foreach (var person in distinctPeople)
            {
                Console.WriteLine(person.Name); 
            }
 
        }
    }
 
    public class Person
    {
        public string SocialSecurityNumber { getset; }
        public string Name { getset; }
 
    }
 
    public class PersonComparer : IEqualityComparer<Person>
    {
 
 
        public bool Equals(Person left, Person right)
        {
            if ((object)left == null && (object)right == null)
            {
                return true;
            }
            if ((object)left == null || (object)right == null)
            {
                return false;
            }
            return left.SocialSecurityNumber == right.SocialSecurityNumber;
        }
 
        public int GetHashCode(Person obj)
        {
            return obj.SocialSecurityNumber.GetHashCode();
        }
 
    }
}
Output:

Pam
John
Susan
Tom

Press any key to continue . . .

No comments:

Post a Comment

Comments will appear once they have been approved by the moderator