С# Как найти, совпадают ли два объекта
Мне нужно знать лучший способ сравнить два объекта и выяснить, если они равны. Я переопределяю 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 имеют одинаковое значение в каждом объекте и, таким образом, отменяют друг друга при хешировании.
Есть ли лучший способ отключить хеширующий объект, чтобы метод, который у меня есть, разрешил мою проблему?
Ответы
Ответ 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);
}
С уважением
К сожалению,