IEqualityComparer GetHashCode被调用,但Equals没有被调用。
IEqualityComparer GetHashCode被调用,但Equals没有被调用。
我有两个列表要进行比较。所以我创建了一个实现了IEqualityComparer
接口的类,请参见下面的代码底部部分。\n当我逐步运行代码时,代码会执行我的GetHashCode
实现,但不执行Equals
方法?尽管我在互联网上阅读了相关内容,但我对GetHashCode
方法并不真正理解它到底是做什么的。\n
ListmissingfactorPayoffList = factorPayoffList.Except( factorPayoffListOrg, new FactorPayoffs.Comparer()).ToList(); List missingfactorPayoffListOrg = factorPayoffListOrg.Except( factorPayoffList, new FactorPayoffs.Comparer()).ToList();
\n因此,在上面的两行代码中,这两个列表返回了所有项目,告诉我这两个列表不包含任何相同的项目。这是不正确的,只有一行是不同的。我猜这是因为Equals
方法没有被调用,这让我怀疑我的GetHashCode
方法是否按照预期工作?\n
class FactorPayoffs { public string FactorGroup { get; set; } public string Factor { get; set; } public DateTime dtPrice { get; set; } public DateTime dtPrice_e { get; set; } public double Ret_USD { get; set; } public class Comparer : IEqualityComparer{ public bool Equals(FactorPayoffs x, FactorPayoffs y) { return x.dtPrice == y.dtPrice && x.dtPrice_e == y.dtPrice_e && x.Factor == y.Factor && x.FactorGroup == y.FactorGroup; } public int GetHashCode(FactorPayoffs obj) { int hash = 17; hash = hash * 23 + (obj.dtPrice).GetHashCode(); hash = hash * 23 + (obj.dtPrice_e).GetHashCode(); hash = hash * 23 + (obj.Factor ?? "").GetHashCode(); hash = hash * 23 + (obj.FactorGroup ?? "").GetHashCode(); hash = hash * 23 + (obj.Ret_USD).GetHashCode(); return hash; } } }
在这段内容中,主要讨论了在实现GetHashCode
方法时,可能会出现GetHashCode
被调用而Equals
方法没有被调用的情况。原因是GetHashCode
被设计成一个快速但粗略的等价性估计方法,所以许多可能涉及大量比较的操作在开始时会通过检查这个结果来判断,而不是调用Equals
方法。只有在必要时才会使用Equals
方法。特别是,如果x.GetHashCode()!=y.GetHashCode()
,那么我们已经知道x.Equals(y)
为false,所以没有理由调用Equals
方法。如果x.GetHashCode()==y.GetHashCode()
,那么x
可能等于y
,但只有调用Equals
方法才能给出明确的答案。
如果你实现的GetHashCode
方法导致对于Equals
返回true
的两个对象,GetHashCode
的返回值不同,那么你的代码就有bug了,许多依赖这些方法的集合类和算法将会默默地失败。
根据这段内容,我们可以得出以下结论:
- GetHashCode
方法的作用是快速但粗略地估计等价性,所以在进行大量比较的操作中,通常会先检查GetHashCode
的结果,而不是直接调用Equals
方法。
- 如果x.GetHashCode()
和y.GetHashCode()
的返回值不相等,那么x.Equals(y)
肯定为false,所以不需要调用Equals
方法。
- 如果x.GetHashCode()
和y.GetHashCode()
的返回值相等,那么x
可能等于y
,但只有调用Equals
方法才能给出明确的答案。
- 在实现GetHashCode
方法时,如果对于Equals
返回true
的两个对象,GetHashCode
的返回值不同,那么代码就有bug了,会导致许多依赖这些方法的集合类和算法失败。
总之,GetHashCode
方法的作用是为了提高比较效率,在使用时需要注意与Equals
方法的一致性,避免出现bug。
问题出现的原因是Equals
和GetHashCode
方法的实现中涉及的属性不同。根据更正式的术语,GetHashCode
对于两个比较相等的对象必须始终返回相同的值。在当前的代码中,只有Ret_USD
值不同的两个对象始终比较相等,但不能保证它们具有相同的哈希码。
因此,当LINQ在两个您认为相等的对象上调用GetHashCode
时,得到的是不同的值,它认为由于值不同,这两个对象不能相等,所以就没有必要调用Equals
方法,于是直接跳过。
要解决这个问题,可以从GetHashCode
方法中移除Ret_USD
因素,或者在Equals
方法中也引入它(根据相等性的语义来决定哪种方式更合理)。
解决问题后,问题得到了解决,但是我需要更多了解哈希码的生成方式,因为我不明白它们是如何生成的。
这里有一个有价值的链接(Guidelines and rules for GetHashCode)可以帮助你更深入地了解。
此前评论中的链接对我来说无效,我猜测应该是这个链接:(Guidelines and rules for GetHashCode)。
你的链接已经损坏,更新后的链接在这里:(Guidelines and rules for GetHashCode)。这对于所有开发人员来说都是必读的。