Как проверить, равны ли два объекта по своим свойствам только без нарушения существующего Object.Equals ()? - PullRequest
10 голосов
/ 20 июня 2011

По сути, GethashCode отличается, даже если они содержат одни и те же значения для свойств ... так почему по умолчанию возвращаются хэш-коды diff?

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?

Есть ли более правильный способ сделать это такЯ не нарушаю принцип работы Object.Equals для моих объектов, но все еще могу иметь собственную проверку равенства на основе значений параметров?

Причина, по которой я спрашиваю, заключается в том, что у меня есть служба: SynchronizeUsers()который загружает массив пользователей.Вместо того, чтобы очищать мой кеш пользователей, я бы просто обновил те, которые должны быть обновлены, удалил те, о которых говорит синхронизация, и добавил новые.Но я не могу просто использовать Object.Equals () для этих объектов.

Ответы [ 7 ]

11 голосов
/ 20 июня 2011

Вы пытались реализовать свой собственный IEqualityComparer? Вы можете передать это перегрузке .Equals (), чтобы определить собственную логику равенства, как в

Пользователь A = Пользователь B, даже если они являются отдельными экземплярами, если свойства x, y, z одинаковы.

Смотрите это: * MSDN 1006 *

Edit: я должен был написать, что вы можете создать экземпляр EqualityComparer и передать два экземпляра его методу Equals () и получить bool. Основное консольное приложение ... покажет true, false, false. Вещи тривиальны, имеют два показанных свойства.

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();
    }
}
9 голосов
/ 29 августа 2015

Если у вас установлен ReSharper (оно того стоит!), То все, что вам нужно сделать, это:

Alt+Insert

С вашим курсором внутри класса. Частичный класс хорош для сокрытия шаблона.

Он автоматически реализует проверку на равенство для каждого свойства.

(выберите все свойства с помощью Ctrl + A, и вы можете проверить все с пробелом!)

3 голосов
/ 20 июня 2011

Рекомендуется переопределить GetHashCode () при переопределении GetEquals ().

http://msdn.microsoft.com/en-us/library/ms173147%28v=vs.80%29.aspx

, например

public override int GetHashCode()
{
    return this.Username.GetHashCode() * this.Id;
}
0 голосов
/ 05 октября 2018

Массив строк - это список исключений для сравнения.Он использует отражение, но производительность очень хорошая.Пожалуйста, проверьте библиотеку Apache Commons Lang 3

CompareToBuilder.reflectionCompare(arg0, arg1, new String[]{"UID", "uidcount"})
0 голосов
/ 20 июня 2011

Если вы хотите просто хешировать вещи, используя метод расширения, чтобы сгенерировать хеш.

public static int GenerateHash(this User myUser){
    return myUser.UserName.GetHashCode() ^ ... other properties....
}

Тогда в вашем коде вы можете сделать:

Console.WriteLine("Hash A: {0} | Hash B: {1}", a.GenerateHash(), b.GenerateHash());

Это будетоставьте все в целости и сохранности, и больше ничего не сломайте.Если вы ищете способ сравнения объектов, вы можете сделать то же самое, используя метод расширения:

public static int AreEqual(this User myUser, User someOther){
    return myUser.UserName == someOther.UserName && ...  other properties.
}

Использование будет выглядеть так:

if(a.AreEqual(b)){
    // these are equal have fun.
}
0 голосов
/ 20 июня 2011

Добавить метод:

public class User
{
    public int UserID { get; set; }

    public bool IsUser(object obj) 
    {
        return (obj is User && ((User)obj).UserID == this.UserID);
    }
}
0 голосов
/ 20 июня 2011

Почему бы не написать свой собственный метод равенства?то есть

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

, где IsEqualTo определен в вашем пользовательском классе как:

Public bool IsEqualTo(user compareTo)
{
  return (UserName == compareTo.UserName && Id == compareTo.Id);
}
...