Compare two collection of objects in c#

I am writing unit tests and have a below Employee class .Basically an employee can have single or more than one address.I want to compare two Employee objects that will return true or false.How can I compare these two objects in the EmployeeEqualityComparer class?

//Employee
public class Employee{

public collection<AddressList> AddressDetails{get;set;}

public string Name{get;set;}

public int Age {get;set;}
}

public class AddressList
{

public string Street{get;set;}
public string Lane{get;set;}
public string City{get;set;}

}
// Implemented IEqualityComparer interface
public class EmployeeEqualityComparer : IEqualityComparer<Employee>
{
public bool Equals(Employee x, Employee y)
{
    
   
}

public int GetHashCode(Employee obj)
{
    return obj.GetHashCode;
}

Open in new window

ksd123Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ramkisan JagtapLead DeveloperCommented:
public bool Equals(Employee x, Employee y)
{
    return  ((object)x).Equals((object)y);   
}

Open in new window

0
ksd123Author Commented:
I am getting false even though both objects contain same items .
0
käµfm³d 👽Commented:
That's because object.Equals compares references, not values. Since you have two different objects in memory, Equals returns false. You need to determine what aspects of your class would make two instances "equal". Say, for example, that two instances are equal if they both have the same value for the Name property. You could adjust your equality comparer in a manner such as this:

public bool Equals(Employee x, Employee y)
{
    return string.Equals(x.Name, y.Name);
}

Open in new window


If you determine that additional properties are needed for equality, then you can simply add those in to your condition:

e.g.

public bool Equals(Employee x, Employee y)
{
    return string.Equals(x.Name, y.Name) &&
           x.Age == y.Age;
}

Open in new window


For your EqualityComparer, you'll probably want to change the name to something that indicates how the comparison(s) work. For my first example, the one that compares names, I would name the comparer as:

public class EmployeeByNameEqualityComparer : IEqualityComparer<Employee>
{
    public bool Equals(Employee x, Employee y)
    {
        return string.Equals(x.Name, y.Name);
    }
}

Open in new window


With this name, it's clear to someone coming behind me how the comparison works, even without inspecting the comparer's definition. I can also have different comparers that compare different properties, so should I ever run into a situation where I need to switch up how two things are considered equal, I can simply swap out the comparer I use.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

ksd123Author Commented:
thank you so much for your explanation.Actually I am writing unit tests and want compare 2 employee objects(expected,actual).Here is my data for employee object(actual) check below code and similar data I will have employee object(expected).Basically an employee can have multiple addresses and am confused how can I set properties and compare two objects.In the  EmployeeByNameEqualityComparer class how can I compare these 2 objects using linq or normal way?

//Fake data
var Emloyeefakeresult=new Employee
{

Name="abc";
Age=32;

AddressDetails=new List<AddressList>(){new AddressList()

          {
		Street=street1;
                Lane=lane1;
                City=NY;
          },
	  {
		Street=street1;
                Lane=lane1;
                City=NY;
          }

}

};

Open in new window

0
Fernando SotoRetiredCommented:
Hi ksd123;

You need to know out of all the properties in the Employee class which properties you want to match against another Employee for the two to be considered as equal. For example in your last post you have an Name and Age property as well as a collection of AddressList. So will two Employee object be equal on just a Employee Name or Employee Name and Age or Employee Name and Age and one member of the AddressList or do ALL properties and ALL collection members must match for two Employee objects are to be considered as equal.
0
ksd123Author Commented:
Hi,
ALL properties and ALL collection members must match for two Employee objects are to be considered as equal
0
käµfm³d 👽Commented:
You'll probably want to implement a comparer for the addresses also:

// Implemented IEqualityComparer interface
public class AddressByAllEqualityComparer : IEqualityComparer<AddressList>
{
    public bool Equals(AddressList x, AddressList y)
    {
        return string.Equals(x.City, y.City) &&
                string.Equals(x.Lane, y.Lane) &&
                string.Equals(x.Street, y.Street);
    }

    public int GetHashCode(AddressList obj)
    {
        return obj.GetHashCode();
    }
}

Open in new window


...and you can simply add the remaining properties to the employee comparer:

// Implemented IEqualityComparer interface
public class EmployeeByAllEqualityComparer : IEqualityComparer<Employee>
{
    public bool Equals(Employee x, Employee y)
    {
        return x.Age == y.Age &&
                string.Equals(x.Name, y.Name) &&
                Enumerable.SequenceEqual(x.AddressDetails, y.AddressDetails, new AddressByAllEqualityComparer());
    }

    public int GetHashCode(Employee obj)
    {
        return obj.GetHashCode();
    }
}

Open in new window


Putting it all together:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace _28525773
{
    class Program
    {
        static void Main(string[] args)
        {
            Employee e1 = new Employee() { Age = 10, Name = "Steve", AddressDetails = new Collection<AddressList>() { new AddressList() { City = "Toledo", Lane = "123", Street = "Anystreet" } } };
            Employee e2 = new Employee() { Age = 10, Name = "Fred", AddressDetails = new Collection<AddressList>() { new AddressList() { City = "Toledo", Lane = "123", Street = "Anystreet" } } };
            Employee e3 = new Employee() { Age = 10, Name = "Steve", AddressDetails = new Collection<AddressList>() { new AddressList() { City = "Los Angeles", Lane = "123", Street = "Anystreet" } } };
            Employee e4 = new Employee() { Age = 10, Name = "Steve", AddressDetails = new Collection<AddressList>() { new AddressList() { City = "Toledo", Lane = "123", Street = "Anystreet" } } };
            EmployeeByAllEqualityComparer comparer = new EmployeeByAllEqualityComparer();

            Console.WriteLine("e1 == e2? {0}", comparer.Equals(e1, e2));
            Console.WriteLine("e1 == e3? {0}", comparer.Equals(e1, e3));
            Console.WriteLine("e1 == e4? {0}", comparer.Equals(e1, e4));
            Console.WriteLine("e2 == e3? {0}", comparer.Equals(e2, e3));
            Console.WriteLine("e2 == e4? {0}", comparer.Equals(e2, e4));
            Console.WriteLine("e3 == e4? {0}", comparer.Equals(e3, e4));
            Console.ReadLine();
        }
    }

    public class Employee
    {

        public Collection<AddressList> AddressDetails { get; set; }

        public string Name { get; set; }

        public int Age { get; set; }
    }

    public class AddressList
    {

        public string Street { get; set; }
        public string Lane { get; set; }
        public string City { get; set; }

    }

    // Implemented IEqualityComparer interface
    public class EmployeeByAllEqualityComparer : IEqualityComparer<Employee>
    {
        public bool Equals(Employee x, Employee y)
        {
            return x.Age == y.Age &&
                    string.Equals(x.Name, y.Name) &&
                    Enumerable.SequenceEqual(x.AddressDetails, y.AddressDetails, new AddressByAllEqualityComparer());
        }

        public int GetHashCode(Employee obj)
        {
            return obj.GetHashCode();
        }
    }

    // Implemented IEqualityComparer interface
    public class AddressByAllEqualityComparer : IEqualityComparer<AddressList>
    {
        public bool Equals(AddressList x, AddressList y)
        {
            return string.Equals(x.City, y.City) &&
                    string.Equals(x.Lane, y.Lane) &&
                    string.Equals(x.Street, y.Street);
        }

        public int GetHashCode(AddressList obj)
        {
            return obj.GetHashCode();
        }
    }
}

Open in new window

0
ksd123Author Commented:
Thank you.Just want to double check  will the above code work if I have multiple addresses for a single employee ? ie

var Emloyeefakeresult=new Employee
{

Name="abc";
Age=32;

AddressDetails=new List<AddressList>(){new AddressList()

          {
		Street=street1;
                Lane=lane1;
                City=NY;
          },
	  {
		Street=street2;
                Lane=lane2;
                City=NJ;
          },

       {
		Street=street3;
                Lane=lane3;
                City=MI;
          },

}

};

Open in new window

0
käµfm³d 👽Commented:
Yes. I haven't looked at the internals, but I believe one of the things that SequenceEqual does is compare the length of the two collections. If the lengths are different, then the two collections cannot be equal.

static void Main(string[] args)
{
    Employee e1 = new Employee() { Age = 10, Name = "Steve", AddressDetails = new Collection<AddressList>() { new AddressList() { City = "Toledo", Lane = "123", Street = "Anystreet" } } };
    Employee e2 = new Employee() { Age = 10, Name = "Fred", AddressDetails = new Collection<AddressList>() { new AddressList() { City = "Toledo", Lane = "123", Street = "Anystreet" } } };
    Employee e3 = new Employee() { Age = 10, Name = "Steve", AddressDetails = new Collection<AddressList>() { new AddressList() { City = "Los Angeles", Lane = "123", Street = "Anystreet" } } };
    Employee e4 = new Employee() { Age = 10, Name = "Steve", AddressDetails = new Collection<AddressList>() { new AddressList() { City = "Toledo", Lane = "123", Street = "Anystreet" }, new AddressList() { City = "London", Lane = "123", Street = "Anystreet" } } };
    EmployeeByAllEqualityComparer comparer = new EmployeeByAllEqualityComparer();

    Console.WriteLine("e1 == e2? {0}", comparer.Equals(e1, e2));
    Console.WriteLine("e1 == e3? {0}", comparer.Equals(e1, e3));
    Console.WriteLine("e1 == e4? {0}", comparer.Equals(e1, e4));
    Console.WriteLine("e2 == e3? {0}", comparer.Equals(e2, e3));
    Console.WriteLine("e2 == e4? {0}", comparer.Equals(e2, e4));
    Console.WriteLine("e3 == e4? {0}", comparer.Equals(e3, e4));
    Console.ReadLine();
}

Open in new window

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.