How do I check if two Objects are equal in terms of their properties only without breaking the existing Object.Equals()?

Viewed 49378

Basically, GethashCode is different even though they contain the SAME values for the properties... so why is the default to return diff hashcodes?

public class User
{
    public Int32 Id { get; set; }
    public String Username { get; set; }
}

User a = new User();
a.Id = 1;
a.Username = "Hello";

User b = new User();
b.Id = 1;
b.Username = "Hello";

Console.WriteLine("Hash A: {0} | Hash B: {1}", a.GetHashCode(), b.GetHashCode());
//Hash A: 37121646 | Hash B: 45592480 <-- these values change each time I rerun the app?

Is there a more proper way to make it so I don't break how Object.Equals works for my objects, but am still able to have my own equality checking based on the parameter values?

The reason I ask is because I have a service: SynchronizeUsers() which downloads an array of users. Instead of clearing out my cache of users, I'd rather just update the ones that need to be updated, remove the ones that the synch says to, and add the new ones. But, I can't just do Object.Equals() on these objects.

9 Answers

Too late to answer, but someone might end up here and I need to know my idea is right or wrong. If strictly values are the consideration, then why not make the objects JSON and compare the JSON strings? Like:

if (JsonConvert.SerializeObject(obj1) == JsonConvert.SerializeObject(obj2)) continue;

Here's a solution that does not require any custom logic in the class and uses generics to ensure both arguments (obj1 and obj2) are the same type at compile time:

  public static class ObjectComparerUtility
  {
    public static bool ObjectsAreEqual<T>(T obj1, T obj2)
    {
      var obj1Serialized = JsonConvert.SerializeObject(obj1);
      var obj2Serialized = JsonConvert.SerializeObject(obj2);

      return obj1Serialized == obj2Serialized;
    }
  }

Usage:

  var c1 = new ConcreteType { Foo = "test1" };
  var c2 = new ConcreteType { Foo = "test1" };
  var areEqual = ObjectComparerUtility.ObjectsAreEqual(c1, c2);
  Assert.IsTrue(areEqual);

The string array is the exclude list for the compare. It uses reflection but the performance is very good. Please check apache commons lang 3 library

CompareToBuilder.reflectionCompare(arg0, arg1, new String[]{"UID", "uidcount"})
Related