[英]SequenceEqual in Equals makes GetHashCode broken
(1) I know that GetHashCode
must return the same number for two objects if they are equal. (1)我知道,如果两个对象相等,则
GetHashCode
必须返回相同的数字。
(2) I also know that SequenceEqual
compare each value of a List
, and Equals(list1, list2)
will return true only if list1
and list2
are the same instance. (2)我也知道
SequenceEqual
比较List
每个值,并且只有list1
和list2
是相同的实例时, Equals(list1, list2)
才返回true。
So, consider this code : 因此,请考虑以下代码:
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);
}
}
I really need this behavior( (2) using SequenceEqual
) for Equals
, mostly for unit testing : make this code Assert.AreEqual(classA1, classA2)
working. 我确实需要
Equals
这种行为( (2)使用SequenceEqual
),主要是用于单元测试:使此代码Assert.AreEqual(classA1, classA2)
运行。
But some of my code is probably broken because in this case 但是我的某些代码可能已损坏,因为在这种情况下
int hash1 = new List<ClassB>().GetHashCode();
int hash2 = new List<ClassB>().GetHashCode();
hash1
and hash2
are not equal. hash1
和hash2
不相等。
So in my ClassA
, (1) is not respected. 因此,在我的
ClassA
,不尊重(1) 。
What is the best solution : 最好的解决方案是什么:
ClassA.Equals
method to use Equals(this.SampleList, other.SampleList)
instead of Enumerable.SequenceEqual(this.SampleList, other.SampleList)
and change all my tests ClassA.Equals
方法以使用Equals(this.SampleList, other.SampleList)
而不是Enumerable.SequenceEqual(this.SampleList, other.SampleList)
并更改所有测试 IEnumerable
implementation where the Equals
overriding is like SequenceEqual
IEnumerable
实现,其Equals
覆盖类似于SequenceEqual
ClassA.GetHashCode
to call GetHashCode
on all list items ClassA.GetHashCode
以在所有列表项上调用GetHashCode
Simply don't base your GetHashCode
on the SampleList
: you don't need to use all the fields/properties in the GetHashCode()
. 只需不要将您的
GetHashCode
基于SampleList
:您不需要使用GetHashCode()
中的所有字段/属性。
For example: 例如:
unchecked
{
return
(this.Str != null ? this.Str.GetHashCode() : 0);
}
or even better use only some information of the SampleList
... The Count
for example: 甚至最好只使用
SampleList
某些信息... Count
例如:
unchecked
{
return
((this.SampleList != null ? this.SampleList.Count.GetHashCode() : 0) * 397) ^
(this.Str != null ? this.Str.GetHashCode() : 0);
}
If you truly want, you can calculate the GetHashCode()
on the elements of the SampleList
. 如果你真的想,你可以计算
GetHashCode()
的的元素 SampleList
。
Now, for the C# obfuscation code tournament, 2016 edition: 现在,对于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);
}
(please don't write it that way... Use a foreach
cycle) (请不要这样写...使用
foreach
循环)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.