(1)我知道GetHashCode
必须为两个对象返回相同的数字(如果它们相等)。
(2)我也知道SequenceEqual
比较List
的每个值,而Equals(list1, list2)
仅在list1
时才会返回true 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);
}
}
对于SequenceEqual
,我确实需要这种行为((2)使用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
答案 0 :(得分:1)
只是不要将GetHashCode
作为SampleList
的基础:您不需要使用GetHashCode()
中的所有字段/属性。
例如:
unchecked
{
return
(this.Str != null ? this.Str.GetHashCode() : 0);
}
甚至更好地仅使用SampleList
的某些信息......例如Count
:
unchecked
{
return
((this.SampleList != null ? this.SampleList.Count.GetHashCode() : 0) * 397) ^
(this.Str != null ? this.Str.GetHashCode() : 0);
}
如果您真的想要,可以计算GetHashCode()
的元素上的SampleList
。
现在,对于C#混淆代码锦标赛,2016版:
unchecked
{
return
(397 * (this.SampleList != null ?
this.SampleList.Aggregate(0, (old, curr) =>
(old * 397) ^ (curr != null ? curr.GetHashCode() : 0)) :
0)
) ^
(this.Str != null ? this.Str.GetHashCode() : 0);
}
(请不要这样写......使用foreach
周期)