Ни один из ответов здесь действительно не подходит мне. Поскольку вы уже сказали, что вы не можете использовать Id
для равенства, и вам нужно использовать набор свойств, вот лучший способ сделать это. Примечание: я не считаю, что в целом это лучший способ реализовать Equals
и GetHashCode
. Это лучшая версия кода ОП.
public override bool Equals(object obj) {
var myClass = obj as MyClass;
if (myClass != null) {
// Order these by the most different first.
// That is, whatever value is most selective, and the fewest
// instances have the same value, put that first.
return this.Id == myClass.Id
&& this.Name == myClass.Name
&& this.Quantity == myClass.Quantity
&& this.Color == myClass.Color;
} else {
// This may not make sense unless GetHashCode refers to `base` as well!
return base.Equals(obj);
}
}
public override int GetHashCode() {
int hash = 19;
unchecked { // allow "wrap around" in the int
hash = hash * 31 + this.Id; // assuming integer
hash = hash * 31 + this.Name.GetHashCode();
hash = hash * 31 + this.Quantity; // again assuming integer
hash = hash * 31 + this.Color.GetHashCode();
}
return hash;
}
См. этот ответ Джона Скита , чтобы узнать некоторые причины этого. Использование xor не годится, потому что различные наборы данных могут в итоге привести к одному и тому же хешу. Этот метод обтекания с простыми числами (начальные значения 19 и 31 выше или другие выбранные вами значения) лучше выполняет сегментацию в «сегменты», каждый из которых имеет несколько коллизий.
Если какое-либо из ваших значений может быть нулевым, я призываю вас тщательно продумать, как они должны сравниваться. Вы могли бы использовать нулевую оценку короткого замыкания и оператор объединения нулей, возможно. Но убедитесь, что, если значения NULL сравниваются как равные, вы назначаете разные хеш-коды различным свойствам, допускающим значение NULL, когда они равны NULL.
Кроме того, я не уверен, что ваша реализация Equals
имеет какой-то смысл. Когда два объекта сравниваются на равенство, сначала сравниваются их значения GetHashCode
. Только если они различаются, запускается метод Equals
(поэтому, если два объекта, хэширующие одно и то же значение, различаются, это будет обнаружено). Поскольку ваша реализация GetHashCode
не ссылается на base
, для вашего Equals
метода может не иметь смысла делать это. В частности, у вас будет серьезная ошибка, ожидающая поломки, если Equals
может вернуть true для двух объектов, хеш-коды которых различны.