2012-03-14 60 views
9

我經常會自我壓倒Equals()GetHashCode()來實現具有相同屬性值的業務對象相同的語義。這導致代碼是重複的寫和脆弱的維持(屬性,都會添加一個/不更新這兩個覆蓋的)。在C#中簡化覆蓋Equals(),GetHashCode()以實現更好的可維護性

的代碼最終看起來像這樣(在實施意見,歡迎):

public override bool Equals(object obj) 
{ 
    if (object.ReferenceEquals(this, obj)) return true; 

    MyDerived other = obj as MyDerived; 

    if (other == null) return false; 

    bool baseEquals = base.Equals((MyBase)other); 
    return (baseEquals && 
     this.MyIntProp == other.MyIntProp && 
     this.MyStringProp == other.MyStringProp && 
     this.MyCollectionProp.IsEquivalentTo(other.MyCollectionProp) && // See http://stackoverflow.com/a/9658866/141172 
     this.MyContainedClass.Equals(other.MyContainedClass)); 
} 

public override int GetHashCode() 
{ 
    int hashOfMyCollectionProp = 0; 
    // http://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/ 
    // BUT... is it worth the extra math given that elem.GetHashCode() should be well-distributed? 
    int bitSpreader = 31; 
    foreach (var elem in MyCollectionProp) 
    { 
     hashOfMyCollectionProp = spreader * elem.GetHashCode(); 
     bitSpreader *= 31; 
    } 
    return base.GetHashCode()^//^is a good combiner IF the combined values are well distributed 
     MyIntProp.GetHashCode()^
     (MyStringProp == null ? 0 : MyStringProp.GetHashValue())^
     (MyContainedClass == null ? 0 : MyContainedClass.GetHashValue())^
     hashOfMyCollectionProp; 
} 

我的問題

  1. 是實現模式的聲音?
  2. 是^充分考慮到有助於元件值均勻分佈?我需要通過31對的-N組合賦予其散列集合元素時分佈均勻繁殖?
  3. 看來這代碼可以被抽象成代碼,使用反射來確定公共屬性,建立的是,手工編碼的溶液相匹配的表達式樹,並根據需要執行表達式樹。這種方法看起來是否合理?有沒有現有的實現?
+2

爲什麼downvote(超過一年發佈之後)?這個問題是非常合法的。如果有什麼問題,請說出來。 – 2013-05-30 17:38:40

回答

4

MSDN其實不是說「不要超載Equals等人的可變類型」。它曾經說,但現在它說:

當你定義一個類或結構,你決定是否有意義 爲 類型創造價值相等(或等值)的自定義。通常情況下,要實現值相等時預期 類型的對象被添加到某種類型的集合,或者當他們 主要目的是存儲一組字段或屬性。

http://msdn.microsoft.com/en-us/library/dd183755.aspx

儘管如此,仍有周圍的哈希碼的穩定性,同時一個目的是在一個散列集合(Dictionary<T,U>HashSet<T>等)參與的複雜性。

我決定選擇兩全其美的,因爲這裏概述:

https://stackoverflow.com/a/9752155/141172

1

我發現我自己忽略equals()和GetHashCode()經常

  • MSDN說:不超載的Equals等人的可變類型

考慮到貢獻組成部分的價值是分散的,是否足夠?

  • 是的,但嘿並不總是均勻分佈。考慮int性能。建議移動一些(小)素數。
+0

MSDN在哪裏說的?我試着用字母搜索文本,只發現了這個問題。 – 2012-03-14 18:53:42

+0

另外...我要看一個簡單的例子,我在重寫Equals的時候看到效用(但也許我錯過了一些東西),你將如何實現一個單元測試,它不會覆蓋給定的MyDerived expected = new MyDerived(){/*初始化* /}; MyDerived actual = DoSomeTest(); Assert.AreEqual(預計,實際)'? – 2012-03-14 18:57:18

+0

關於^ ...在我的情況下,每個XORed值是GetHashCode()的結果,應該合理分佈。正如所實施的,你看到我如何使用^的缺陷?即使每個集合元素的哈希都是GetHashCode()的結果,您是否會將集合元素乘以一個素數? – 2012-03-14 18:59:49

0

也許我很困惑在這裏,但不應該在上null檢查返回1而不是0在GetHashCode重寫?

所以

MyStringProp == null ? 0 : MyStringProp.GetHashValue() 

應該

MyStringProp == null ? 1 : MyStringProp.GetHashValue() 
相關問題