3

I have the below entity

public class Employee
{
    public int EmpId { get; set; }
 }

How can I compare between the objects? Thanks

mcUser1
  • 39
  • 2
  • So what you want as result is a new list containing all elements that exist both in lst1 and lst2, and to be equal that means that all of the properties must be equal to eachother? – Øyvind Bråthen Jul 28 '11 at 06:54
  • 2
    super duplicate of [Comparing two collections for equality](http://stackoverflow.com/questions/50098/comparing-two-collections-for-equality) and a million more (look in the related questions) – Alastair Pitts Jul 28 '11 at 06:54
  • @Alastair - Does not seem the same to me. That question checks if two collections of primitive objects are equal. This one checks individual complex items in two different lists towards each other. – Øyvind Bråthen Jul 28 '11 at 07:03

4 Answers4

5

Implement IEquatable<T> on your type (in this case Employee), and then use Enumerable.SequenceEqual:

bool equal = Enumerable.SequenceEqual(lst1, lst2);

If you cannot modify the Employee class, you can also create a custom IEqualityComparer<T> for Employee and use the other overload of Enumerable.SequenceEqual.

bool equal = lst1.SequenceEqual(lst2, new EmployeeComparer());

Note that this considers two collections equal only if they contain equal objects in the same order.

If the order of the items doesn't matter I would use something like this:

bool equal = lst1.Count == lst2.Count && lst1.Count == lst1.Intersect(lst2).Count();

You can also use an IEqualityComparer<T> with Intersect.

Update:

It seems you want to be able to compare any object even if they don't implement IEquatable<T>. Below is a sample of an equality comparer that will use IEquatable<T> if it's available, Enumerable.SequenceEqual if the type is a collection, and otherwise recursively check the public properties of the type using reflection:

class ReflectionComparer<T> : IEqualityComparer<T>
{
    public bool Equals(T x, T y)
    {
        Type type = typeof(T);
        if( typeof(IEquatable<T>).IsAssignableFrom(type) )
            return EqualityComparer<T>.Default.Equals(x, y);

        Type enumerableType = type.GetInterface(typeof(IEnumerable<>).FullName);
        if( enumerableType != null )
        {
            Type elementType = enumerableType.GetGenericArguments()[0];
            Type elementComparerType = typeof(ReflectionComparer<>).MakeGenericType(elementType);
            object elementComparer = Activator.CreateInstance(elementComparerType);
            return (bool)typeof(Enumerable).GetMethod("SequenceEqual")
                                           .MakeGenericMethod(elementType)
                                           .Invoke(null, new object[] { x, y, elementComparer });
        }

        foreach( PropertyInfo prop in type.GetProperties() )
        {
            Type propComparerType = typeof(ReflectionComparer<>).MakeGenericType(prop.PropertyType);
            object propComparer = Activator.CreateInstance(propComparerType);
            if( !((bool)typeof(IEqualityComparer<>).MakeGenericType(prop.PropertyType)
                                                   .GetMethod("Equals")
                                                   .Invoke(propComparer, new object[] { prop.GetValue(x, null), prop.GetValue(y, null) })) )
                return false;
        }
        return true;
    }

    public int GetHashCode(T obj)
    {
        throw new NotSupportedException();
    }
}

I didn't implement GetHashCode because it is not needed by Enumerable.SequenceEqual.

This should be able to do what you want (but be warned this is not exactly efficient; don't use this in performance critical code).

Sven
  • 21,903
  • 4
  • 56
  • 63
  • @mcUser1: I have added a generic `IEqualityComparer` implementation that will use reflection to compare the objects if no better way exists. Hopefully this will help you. – Sven Jul 28 '11 at 08:22
1

You will need to implement IEqualityComparer for your objects and then use that in Union method

Ankur
  • 33,367
  • 2
  • 46
  • 72
0

Override Equals() and GetHashCode() methods in your Employee class

public class Employee
{
    public int EmpId { get; set; }
    public string EmpName { get; set; }
    public int EmpAge { get; set; }
    public string EmpSex { get; set; }

    public override bool Equals(object obj)
    {
        Employee other = obj as Employee;
        return null != other
               && other.EmpId == this.EmpId
               && other.EmpName == this.EmpName
               && other.EmpAge == this.EmpAge
               && other.EmpSex == this.EmpSex;
    }

    public override int GetHashCode()
    {
        return (EmpId + "_" + EmpName + "_" + EmpAge + "_" + EmpSex).GetHashCode();
    }
}


bool AreEqual<T>(IEnumerable<T> ls1, IEnumerable<T> ls2)
{
    return ls1.Count() == ls2.Count() && !ls1.Any(e => !ls2.Contains(e)) && !ls2.Any(e => !ls1.Contains(e));
}

    void Test()
    {
        Employee e1 = new Employee() { EmpAge = 20, EmpId = 123, EmpName = "XYZ", EmpSex = "M" };
        Employee e2 = new Employee() { EmpAge = 20, EmpId = 1232, EmpName = "XYZ", EmpSex = "M" };
        Employee e3 = new Employee() { EmpAge = 20, EmpId = 1232, EmpName = "XYA", EmpSex = "M" };
        Employee e4 = new Employee() { EmpAge = 20, EmpId = 1232, EmpName = "XYF", EmpSex = "M" };

        List<Employee> ls1 = new List<Employee>{e4, e3, e1, e2};
        List<Employee> ls2 = new List<Employee>{e1, e2, e3, e4};

        bool result = AreEqual(ls1, ls2); // true

        ls1 = new List<Employee>{e4, e3, e1, e3};
        ls2 = new List<Employee>{e1, e2, e3, e4};

        result = AreEqual(ls1, ls2); // false
    }
Marek Musielak
  • 26,832
  • 8
  • 72
  • 80
0

You might think of using reflection out here if you intended to compare two instances of any type BUT i am sure this is not the correct way , we are just taking advantage of framework.

as a hacked solution, you may see below code.

 static void Main(string[] args)
    {
        Employee e1 = new Employee() { EmpAge = 20, EmpId = 123, EmpName = "XYZ", EmpSex = "M" };
        Employee e2 = new Employee() { EmpAge = 20, EmpId = 123 , EmpName = "XYq", EmpSex = "M" };

        Person p1 = new Person() { Age = 20, name ="ABC"  };
        Person p2 = new Person() { Age = 20, name = "ABC" };

        Console.WriteLine("Employee Equality :" + IsObjectEquals(e1, e2).ToString());
        Console.WriteLine("Person Equality :" +IsObjectEquals(p1, p2).ToString());
        Console.ReadLine();
    }


    public static bool IsObjectEquals(object obj1, object obj2)
    {

       PropertyInfo[] props1 = obj1.GetType().GetProperties();
       PropertyInfo[] props2 = obj2.GetType().GetProperties();



       foreach (PropertyInfo pinfo in props1)
       {
           var val1 = pinfo.GetValue(obj1, null);
           var val2 = pinfo.GetValue(obj2, null);

           if (val1.ToString().Trim() != val2.ToString().Trim())
           {
                    return false;
           }


       }

       return true;

    }
TalentTuner
  • 17,262
  • 5
  • 38
  • 63