Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 814
michael Avatar asked Jun 20 '11 14:06

michael


3 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;
like image 113
Md. Rasedur Rahman Roxy Avatar answered Oct 25 '22 07:10

Md. Rasedur Rahman Roxy


If you have ReSharper installed (it's worth it!) then all you have to do is:

Alt+Insert

With your cursor inside the class. A partial class is good for hiding the boilerplate.

It'll automatically implement an equality check for each property.

(Select all properties w/ Ctrl+A, and you can check all w/ Space!)

like image 30
RJB Avatar answered Oct 25 '22 06:10

RJB


Have you tried implementing your own IEqualityComparer? You can pass this to an .Equals() overload to define your own custom equality logic, as in

User A = User B even if they are distinct instances, if properties x, y, z are the same.

See this: MSDN

Edit: I should have written you can instantiate your EqualityComparer and pass two instances to its Equals() method and get a bool. Basic console app... will show true, false, false. Thing is trivial, has the two properties shown.

var comparer = new ThingEqualityComparer();

Console.WriteLine(comparer.Equals(new Thing() { Id = 1, Name = "1" }, new Thing() { Id = 1, Name = "1" }));
Console.WriteLine(comparer.Equals(new Thing() { Id = 1, Name = "1" }, new Thing() { Id = 2, Name = "2" }));
Console.WriteLine(comparer.Equals(new Thing() { Id = 1, Name = "1" }, null));


class ThingEqualityComparer : IEqualityComparer<Thing>
{
    public bool Equals(Thing x, Thing y)
    {
        if (x == null || y == null)
            return false;

        return (x.Id == y.Id && x.Name == y.Name);
    }

    public int GetHashCode(Thing obj)
    {
        return obj.GetHashCode();
    }
}
like image 33
pelazem Avatar answered Oct 25 '22 07:10

pelazem