Подтвердить что ты не робот

С# Как найти, совпадают ли два объекта

Мне нужно знать лучший способ сравнить два объекта и выяснить, если они равны. Я переопределяю GethashCode и Equals. Итак, базовый класс выглядит следующим образом:

public class Test
{
    public int Value { get; set; }
    public string String1 { get; set; }
    public string String2 { get; set; }

    public override int GetHashCode()
    {
        return Value ^ String1.GetHashCode() ^ String2.GetHashCode();
    }

    public override bool Equals( object obj )
    {
        return GetHashCode() == obj.GetHashCode();
    }
}

Итак, для целей тестирования я создал два объекта:

Test t = new Test()
{
    Value = 1,
    String1 ="One",
    String2 = "One"
};

Test t2 = new Test()
{
    Value = 1,
    String1 = "Two",
    String2 = "Two"
};

bool areEqual = t.Equals( t2 );

При тестировании thisEqual возвращает истинное событие, хотя оба объекта разные. Я понимаю, что это потому, что String1 и String2 имеют одинаковое значение в каждом объекте и, таким образом, отменяют друг друга при хешировании.

Есть ли лучший способ отключить хеширующий объект, чтобы метод, который у меня есть, разрешил мою проблему?

4b9b3361

Ответ 1

Ваш текущий метод равенства нарушен - есть больше значений, чем возможные хэш-коды. Это вполне разумно (и ожидается), что вы будете иногда иметь значения, которые не равны, но дают одинаковый хеш. Равные значения должны проверять фактические значения:

public override bool Equals(object obj)
{
    Test test = obj as Test;
    if (obj == null)
    {
        return false;
    }
    return Value == test.Value &&
        String1 == test.String1 &&
        String2 == test.String2;
}

Несколько замечаний:

  • Ваш способ генерации hashcode даст одинаковое значение для любого фиксированного Value, если String1 и String2 совпадают; он также взорвется, если String1 или String2 равно null. Это неудачный аспект использования XOR для хеширования. Я предпочитаю что-то вроде этого:

    // Put this extension method in a utility class somewhere
    public static int SafeGetHashCode<T>(this T value) where T : class
    {
        return value == null ? 0 : value.GetHashCode();
    }
    
    // and this in your actual class
    public override int GetHashCode()
    {
        int hash = 19;
        hash = hash * 31 + Value;
        hash = hash * 31 + String1.SafeGetHashCode();
        hash = hash * 31 + String2.SafeGetHashCode();
        return hash;
    }
    
  • Вообще говоря, равенство становится сложным, когда задействовано наследование. Вы можете захотеть запечатать свой класс.

  • Вы также можете реализовать IEquatable<Test>

Ответ 2

Ваш Equals неверный - определить, что означает, что для двух вещей будет одинаковым; и с тем же хэш-кодом не означает равенство (однако, другой хеш-код означает означает неравномерность). Если "равенство" означает "обе строки попарно равны", то test, что.

Повторите лучший хеш; xor для этого печально известно, так как тривиально получить 0 через xor значение с самим собой. Лучшим подходом может быть что-то вроде:

int i = 0x65407627;
i = (i * -1521134295) + Value.GetHashCode();
i = (i * -1521134295) + (String1 == null ? 0 : String1.GetHashCode());
i = (i * -1521134295) + (String2 == null ? 0 : String2.GetHashCode());
return i;

Ответ 3

простой

Object.Equals(obj1, obj2);

Ответ 4

В дополнение ко всем великим ответам я бы рекомендовал вам прочитать эту статью статью от Алоиса Крауса

Ответ 5

Для любых двух объектов, равенство объекта подразумевает равенство хэш-кода, однако равенство хэш-кода не означает равенства объектов. Из Object.GetHashCode в MSDN:

Функция хеширования должна иметь следующие свойства:

Если два объекта сравниваются как равные, Метод GetHashCode для каждого объекта должен возвращать одно и то же значение. Однако, если два объекта не сравниваются как равно, методы GetHashCode для два объекта не должны возвращаться разные значения.

Другими словами, ваш Equals написан неправильно. Это должно быть что-то вроде:

public override bool Equals(object obj)
{
    Test other = obj as Test;
    if (other == null)
        return false;

    return (Value == other.Value)
        && (String1 == other.String1)
        && (String2 == other.String2);
}

GetHashCode хорош для коллекций (например, Dictionary<K, V>), чтобы быстро определить приблизительное равенство. Equals предназначен для сравнения, если два объекта действительно одинаковы.

Ответ 6

Ну!!!!! (MSDN)

Ответ 7

Вы можете сериализовать два объекта в JSON, а затем сравнить две строки, чтобы убедиться, что они одинаковые.

Например

JavaSriptSerializer serialiser = new JavaScriptSerializer();

string t1String = serialiser.Serialize(t);
string t2String = serialiser.Serialize(t2);

if(t1String == t2String)
   return true; //they are equal
else
   return false;

Ответ 8

не будет функцией Equals всегда проверять только на тот же тип, не так ли:

//override
    public bool Equals(Test other)//(object obj) 
    {
        //return GetHashCode() == obj.GetHashCode();
        return (Value == other.Value) &&
               (String1 == other.String1) &&
               (String2 == other.String2);
    }

С уважением К сожалению,