IEqualityComparer正在调用GetHashCode但是Equals not

mHe*_*pMe 14 c#

我有两个列表,我想比较.所以我创建了一个实现IEqualityComparer接口的类,请参见下面的代码底部.

当我单步GetHashCode执行代码时,代码会通过我的实现而不是EqualsGetHashCode尽管在互联网上阅读以及它到底在做什么,但我并不真正理解这种方法.

List<FactorPayoffs> missingfactorPayoffList = 
    factorPayoffList.Except(
        factorPayoffListOrg,
        new FactorPayoffs.Comparer()).ToList();

List<FactorPayoffs> missingfactorPayoffListOrg =
    factorPayoffListOrg.Except(
        factorPayoffList,
        new FactorPayoffs.Comparer()).ToList();
Run Code Online (Sandbox Code Playgroud)

所以在上面的两行代码中,两个列表返回每个项目,告诉我这两个列表不包含任何相同的项目.事实并非如此,只有不同的行.我猜这种情况正在发生,因为该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;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

Jon*_*Jon 25

EqualsGetHashCode实现应该涉及完全相同的属性集; 他们不.

在更正式的术语中,GetHashCode 必须始终为两个比较相等的对象返回相同的值.使用当前代码,两个仅在Ret_USD值上不同的对象将始终比较相等,但不保证具有相同的哈希码.

所以会发生什么是LINQ调用GetHashCode你认为相等的两个对象,得到不同的值,得出的结论是,由于值不同,对象不能相等,所以在调用Equals和移动时根本就没有意义.

要解决这个问题,要么Ret_USDGetHashCode内部删除因子,要么在里面引入它Equals(对于你的相等语义来说是有意义的).

  • @mHelpMe [这是一个有价值的链接](http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx) (3认同)

Sam*_*ell 13

GetHashCode旨在作为一个快速但粗略的相等估计,因此许多可能涉及大量比较的操作都是从检查此结果开始,而不是EqualsEquals在必要时使用.特别是,如果x.GetHashCode()!=y.GetHashCode(),那么我们已经知道x.Equals(y)是假的,所以没有理由打电话Equals.有x.GetHashCode()==y.GetHashCode(),则x 可能等同y,而只是调用Equals会给出一个明确的答案.

如果你GetHashCode以一种导致GetHashCode两个Equals返回对象不同的方式实现true,那么你的代码中就会有一个错误,依赖这些方法的许多集合类和算法都会无声地失败.


Mas*_*lce 7

如果要强制执行Equals,可以按如下方式实现

public int GetHashCode(FactorPayoffs obj) {
        return 1;
    }
Run Code Online (Sandbox Code Playgroud)