Solved

Compare two  collection of objects in c#

Posted on 2014-09-25
9
301 Views
Last Modified: 2014-10-07
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

0
Comment
Question by:ksd123
9 Comments
 
LVL 12

Expert Comment

by:Ramkisan Jagtap
Comment Utility
public bool Equals(Employee x, Employee y)
{
    return  ((object)x).Equals((object)y);   
}

Open in new window

0
 

Author Comment

by:ksd123
Comment Utility
I am getting false even though both objects contain same items .
0
 
LVL 74

Accepted Solution

by:
käµfm³d   👽 earned 500 total points
Comment Utility
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
 

Author Comment

by:ksd123
Comment Utility
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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 62

Expert Comment

by:Fernando Soto
Comment Utility
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
 

Author Comment

by:ksd123
Comment Utility
Hi,
ALL properties and ALL collection members must match for two Employee objects are to be considered as equal
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
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
 

Author Comment

by:ksd123
Comment Utility
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
 
LVL 74

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 500 total points
Comment Utility
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

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

IntroductionWhile developing web applications, a single page might contain many regions and each region might contain many number of controls with the capability to perform  postback. Many times you might need to perform some action on an ASP.NET po…
Introduction This article shows how to use the open source plupload control to upload multiple images. The images are resized on the client side before uploading and the upload is done in chunks. Background I had to provide a way for user…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now