簡體   English   中英

IEqualityComparer正在調用GetHashCode,但不是Equals

[英]IEqualityComparer GetHashCode being called but Equals not

我有兩個列表,我想比較。 所以我創建了一個實現IEqualityComparer接口的類,請參見下面的代碼底部。

當我單步執行代碼時,代碼會通過我的GetHashCode實現而不是Equals 我不太了解GetHashCode方法,盡管在互聯網上閱讀以及它到底在做什么。

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

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

因此,在上面的兩行代碼中,兩個列表返回每個項目,告訴我這兩個列表不包含任何相同的項目。 事實並非如此,只有不同的行。 我猜這種情況正在發生,因為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;
            }
        }
    }

您的EqualsGetHashCode實現應該涉及完全相同的屬性集; 他們不。

在更正式的術語中, GetHashCode 必須始終為兩個比較相等的對象返回相同的值。 使用當前代碼,兩個僅在Ret_USD值上不同的對象將始終比較相等,但不保證具有相同的哈希碼。

所以會發生什么是LINQ在你認為相等的兩個對象上調用GetHashCode ,得到不同的值,得出的結論是,由於值不同,對象不能相等所以在調用Equals並繼續前進時根本就沒有意義。

要解決這個問題,可以從GetHashCode刪除Ret_USD因子,也可以在Equals引入它(對於你的相等語義都是有意義的)。

GetHashCode旨在作為一個快速但粗略的相等估計,因此許多可能涉及大量比較的操作首先檢查此結果而不是Equals ,並且僅在必要時使用Equals 特別是,如果x.GetHashCode()!=y.GetHashCode() ,那么我們已經知道x.Equals(y)為false,因此沒有理由調用Equals 如果x.GetHashCode()==y.GetHashCode() ,則x 可能等於y ,但只有對Equals的調用才會給出明確的答案。

如果實現GetHashCode的方式導致GetHashCode對於Equals返回true兩個對象不同,那么您的代碼中就會出現錯誤,許多依賴於這些方法的集合類和算法將無聲地失敗。

如果要強制執行Equals,可以按如下方式實現

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

像這樣重寫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;
    }
}

注意,您應該使用unchecked因為您不關心溢出。 另外,合並到string.Empty是毫無意義的浪費,只是從哈希中排除。

在這里查看我知道的最佳通用答案

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM