(1) Я знаю, что GetHashCode
должен возвращать одинаковое число для двух объектов, если они равны.SequenceEqual in Equals делает GetHashCode сломанным
(2) Я также знаю, что SequenceEqual
сравнить каждое значение List
и Equals(list1, list2)
возвращает истину, только если list1
и list2
те же инстанции.
Итак, рассмотрим следующий код:
public List<ClassB> SampleList { get; set; }
public string Str { get; set; }
protected bool Equals(Uncorrectable other)
{
return Enumerable.SequenceEqual(this.SampleList, other.SampleList) && string.Equals(this.Str, other.Str);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) { return false; }
if (ReferenceEquals(this, obj)) { return true; }
if (obj.GetType() != this.GetType()) { return false; }
return this.Equals((ClassA) obj);
}
public override int GetHashCode()
{
unchecked
{
return
((this.SampleList != null ? this.SampleList.GetHashCode() : 0)*397)^
(this.Str != null ? this.Str.GetHashCode() : 0);
}
}
мне действительно нужно это поведение ((2) с использованием SequenceEqual
) для Equals
, в основном для модульного тестирования: сделать этот код Assert.AreEqual(classA1, classA2)
работает.
Но некоторые из моего кода, вероятно, сломана, потому что в этом случае
int hash1 = new List<ClassB>().GetHashCode();
int hash2 = new List<ClassB>().GetHashCode();
hash1
и hash2
не равны.
Так что в моем ClassA
, (1) не соблюдается.
Что является лучшим решением:
- Изменить
ClassA.Equals
метод использоватьEquals(this.SampleList, other.SampleList)
вместоEnumerable.SequenceEqual(this.SampleList, other.SampleList)
и изменить все мои тесты - Создайте другой
IEnumerable
реализации, гдеEquals
наиважнейшая, какSequenceEqual
- Изменить
ClassA.GetHashCode
в звонитеGetHashCode
по всем статьям списка - ничего не делать
- Еще один?
Так сейчас очевидно (где-то в мозг был идеей того, что обратное ** (1) ** должно быть истинным).Если ClassA не предназначен для большого списка (у меня будет только 10 различных экземпляров ClassA), и что мне действительно не нужна производительность, согласны ли мы с тем, что я могу использовать второе решение (используя длину или другое поле)? – ZwoRmi
@ ZwoRmi Да. Обратите внимание, что вычисление хэша большого 'SampleList' может быть очень длинным в общем ... Так например, вы могли бы даже« обмануть »и включить в хэш только фиксированное подмножество этого ...' (this.SampleList.Count * 397)^this.SampleList.Take (5) .Aggregate' – xanatos
Если вы просто полностью игнорируете список, вероятность столкновения, вероятно, будет * очень * высокой, что приведет к очень низкой производительности того, что использует хэш-код. – Servy