![](/img/trans.png)
[英]Neither Equals nor GetHashCode get called on IEqualityComparer
[英]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;
}
}
}
您的Equals
和GetHashCode
實現應該涉及完全相同的屬性集; 他們不。
在更正式的術語中, 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.