Tuesday, April 12, 2016

Diffence between list of user defined types

Shout it kick it on DotNetKicks.com
Below is discussion about finding out difference between two lists of elements.

Easiest way to find out difference between two list is make use of method Except, which is introduced with Linq feature in .Net framework 3.5.

Except method works as below



So when except method is applied on two List A and List B, it get list of all element which are present in list A only.

Let’s understand same by writing Code

List a = new List() { 2, 4, 7, 9, 4 };
List b = new List() { 8, 6, 7, 3, 4 };

var lst = a.Except(b);
foreach (var ele in lst)
{
    Console.WriteLine(ele);
}

Above code defines two list of integer, and apply Except method to find difference between them.

Output 
 


Output prints 2 & 9, which are the element in “List a” and not in “List b”. If one want to find out element which are present in “List b” and not in “List a”, than code will be like

var lst = b.Except(a);//pint output 8,6 & 3

Note:
Except method returns element of the collection which is on left side, it doesn’t get list of those element of the right side collection element which is not part of left side collection.

Except on User Defined typed List
Below is explain about how Except works when applied on user-defined data type, to understand this let’s defined employee class

public class Employee
{
    public int ID { get; set; }
    public string Name { get; set; }
}

After defining Employee class below code creates two list of Employee and applies Except method on it

List lstA = new List() { new Employee { ID = 1, Name = "Abc" }, 
                         new Employee { ID = 2, Name = "Pranay" },
                         new Employee { ID = 3, Name = "Hemang" }}; 
 
List lstB = new List() { new Employee { ID = 4, Name = "Xyz" }, 
                         new Employee { ID = 2, Name = "Pranay" },
                         new Employee { ID = 5, Name = "Virendra" }};

var lst = lstB.Except(lstA);
foreach (var ele in lst)
{
     Console.WriteLine(ele.ID + " " + ele.Name);
}

Output 
 


So output print out all the element of list B, rather than printing elements which are not present in list A.
Problem here is when Except method applied on user-defined datatype it tries to compare references of object to find difference between lists.

Resolution 
To resolve problem, there is need to use Except overload method which takes list as first input and Custom Equality Comparer as its second parameter for type. Custom Equality comparer helps to do comparison between object of list and returns difference between list.

public class EmployeeComparer : IEqualityComparer
{
     bool IEqualityComparer.Equals(Employee x, Employee y)
     {
        if (x == null || y == null)
            return false;

        return x.ID == y.ID;
     }

    int IEqualityComparer.GetHashCode(Employee obj)
    {
       if (obj == null)
           return 0;

       return obj.ID.GetHashCode();
    }
}

Above code defines Custom Employee comparer which implements IEqualityComparer and does comparison of employee objects based on ID property defined in employee class.

Now when Except method applied on list as in below code,

List lstA = new List() { new Employee { ID = 1, Name = "Abc" }, 
                         new Employee { ID = 2, Name = "Pranay" },
                         new Employee { ID = 3, Name = "Hemang" }};

List lstB = new List() { new Employee { ID = 4, Name = "Xyz" }, 
                         new Employee { ID = 2, Name = "Pranay" },
                         new Employee { ID = 5, Name = "Virendra" }};

var lst = lstB.Except(lstA, new EmployeeComparer());
foreach (var ele in lst)
{
     Console.WriteLine(ele.ID + " " + ele.Name);
}

Output 
 


Output prints element of list B which are not present in List A of employee. So comparer makes it easy to find difference between two lists.