IEqualityComparer GetHashCode被调用,但Equals没有被调用。

18 浏览
0 Comments

IEqualityComparer GetHashCode被调用,但Equals没有被调用。

我有两个列表要进行比较。所以我创建了一个实现了IEqualityComparer接口的类,请参见下面的代码底部部分。\n当我逐步运行代码时,代码会执行我的GetHashCode实现,但不执行Equals方法?尽管我在互联网上阅读了相关内容,但我对GetHashCode方法并不真正理解它到底是做什么的。\n

List missingfactorPayoffList = 
    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;
            }
        }
    }

0
0 Comments

从上述内容中可以得出以下结论:

问题的出现原因是:GetHashCode()方法被调用,但是Equals()方法没有被调用。

解决方法是:实现Equals()方法,并在其中调用GetHashCode()方法,可以强制执行Equals()方法。具体实现如下:

public int GetHashCode(FactorPayoffs obj) {
    return 1;
}

然而,需要注意的是,使用此方法时要小心。如果在一个紧密的循环中使用,这样做可能会导致严重的性能损失,因为你绕过了所有对象的GetHashCode()方法。

0
0 Comments

在这段内容中,主要讨论了在实现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。

0
0 Comments

问题出现的原因是EqualsGetHashCode方法的实现中涉及的属性不同。根据更正式的术语,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)。这对于所有开发人员来说都是必读的。

0