[英]IEqualityComparer GetHashCode being called but Equals not
I have two lists that I am trying to compare. 我有两个列表,我想比较。 So I have created a class that implements the
IEqualityComparer
interface, please see below in the bottom section of code. 所以我创建了一个实现
IEqualityComparer
接口的类,请参见下面的代码底部。
When I step through my code, the code goes through my GetHashCode
implementation but not the Equals
? 当我单步执行代码时,代码会通过我的
GetHashCode
实现而不是Equals
? I do not really understand the GetHashCode
method, despite reading around on the internet and what exactly it is doing. 我不太了解
GetHashCode
方法,尽管在互联网上阅读以及它到底在做什么。
List<FactorPayoffs> missingfactorPayoffList =
factorPayoffList.Except(
factorPayoffListOrg,
new FactorPayoffs.Comparer()).ToList();
List<FactorPayoffs> missingfactorPayoffListOrg =
factorPayoffListOrg.Except(
factorPayoffList,
new FactorPayoffs.Comparer()).ToList();
So in the two lines of code above the two lists return me every item, telling me that the two lists do not contain any items that are the same. 因此,在上面的两行代码中,两个列表返回每个项目,告诉我这两个列表不包含任何相同的项目。 This is not true, there is only row that is different.
事实并非如此,只有不同的行。 I'm guessing this is happening because the
Equals
method is not getting called which in turns makes me wonder if my GetHashCode
method is working as its supposed to? 我猜这种情况正在发生,因为
Equals
方法没有被调用,这反过来让我想知道我的GetHashCode
方法是否正常工作?
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<FactorPayoffs>
{
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;
}
}
}
Your Equals
and GetHashCode
implementations should involve the exact same set of properties; 您的
Equals
和GetHashCode
实现应该涉及完全相同的属性集; they do not. 他们不。
In more formal terms, GetHashCode
must always return the same value for two objects that compare equal. 在更正式的术语中,
GetHashCode
必须始终为两个比较相等的对象返回相同的值。 With your current code, two objects that differ only in the Ret_USD
value will always compare equal but are not guaranteed to have the same hash code. 使用当前代码,两个仅在
Ret_USD
值上不同的对象将始终比较相等,但不保证具有相同的哈希码。
So what happens is that LINQ calls GetHashCode
on two objects you consider equal, gets back different values, concludes that since the values were different the objects cannot be equal so there's no point at all in calling Equals
and moves on. 所以会发生什么是LINQ在你认为相等的两个对象上调用
GetHashCode
,得到不同的值,得出的结论是,由于值不同,对象不能相等所以在调用Equals
并继续前进时根本就没有意义。
To fix the problem, either remove the Ret_USD
factor from GetHashCode
or introduce it also inside Equals
(whatever makes sense for your semantics of equality). 要解决这个问题,可以从
GetHashCode
删除Ret_USD
因子,也可以在Equals
引入它(对于你的相等语义都是有意义的)。
GetHashCode
is intended as a fast but rough estimate of equality, so many operations potentially involving large numbers of comparisons start by checking this result instead of Equals
, and only use Equals
when necessary. GetHashCode
旨在作为一个快速但粗略的相等估计,因此许多可能涉及大量比较的操作首先检查此结果而不是Equals
,并且仅在必要时使用Equals
。 In particular, if x.GetHashCode()!=y.GetHashCode()
, then we already know x.Equals(y)
is false, so there is no reason to call Equals
. 特别是,如果
x.GetHashCode()!=y.GetHashCode()
,那么我们已经知道x.Equals(y)
为false,因此没有理由调用Equals
。 Had x.GetHashCode()==y.GetHashCode()
, then x
might equal y
, but only a call to Equals
will give a definite answer. 如果
x.GetHashCode()==y.GetHashCode()
,则x
可能等于y
,但只有对Equals
的调用才会给出明确的答案。
If you implement GetHashCode
in a way that causes GetHashCode
to be different for two objects where Equals
returns true
, then you have a bug in your code and many collection classes and algorithms relying on these methods will silently fail. 如果实现
GetHashCode
的方式导致GetHashCode
对于Equals
返回true
两个对象不同,那么您的代码中就会出现错误,许多依赖于这些方法的集合类和算法将无声地失败。
If you want to force the execution of the Equals you can implement it as follows 如果要强制执行Equals,可以按如下方式实现
public int GetHashCode(FactorPayoffs obj) {
return 1;
}
Rewrite you GetHashCode
implementation like this, to match the semantics of your Equals
implementation. 像这样重写
GetHashCode
实现,以匹配Equals
实现的语义。
public int GetHashCode(FactorPayoffs obj)
{
unchecked
{
int hash = 17;
hash = hash * 23 + obj.dtPrice.GetHashCode();
hash = hash * 23 + obj.dtPrice_e.GetHashCode();
if (obj.Factor != null)
{
hash = hash * 23 + obj.Factor.GetHashCode();
}
if (obj.FactorGroup != null)
{
hash = hash * 23 + obj.FactorGroup.GetHashCode();
}
return hash;
}
}
Note, you should use unchecked
because you don't care about overflows. 注意,您应该使用
unchecked
因为您不关心溢出。 Additionaly, coalescing to string.Empty
is pointlessy wasteful, just exclude from the hash. 另外,合并到
string.Empty
是毫无意义的浪费,只是从哈希中排除。
See here for the best generic answer I know , 在这里查看我知道的最佳通用答案 ,
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.