2013-04-11 53 views
1

方法有來自NHibernate文檔一段話:Implemeting GetHashCode的,等於爲ValueObjects

注:如果定義複合元素的ISet,它實現Equals()GetHashCode()正確是非常重要的。

correctly是什麼意思?是否需要爲域中的所有值對象實現這些方法?

延長我的問題

在文章馬克連接用戶白漿狀態:

它實際上很難正確地實現GetHashCode(),因爲,除了規則的馬克已經提到,哈希代碼不應該在對象的生命週期中更改。因此,用於計算哈希代碼的字段必須是不可變的。

當我使用NHibernate時,終於找到了解決此問題的解決方案。我的方法是從對象的ID中計算哈希碼。 ID只能通過構造函數設置,所以如果你想改變ID,這是不太可能的,你必須創建一個新的對象,它有一個新的ID,因此一個新的哈希碼。這種方法最適合於GUID,因爲您可以提供一個隨機生成ID的無參數構造函數。

我突然意識到我有我的AbstractEntity類中:

public abstract class AbstractEntity<T> where T : AbstractEntity<T> { 
    private Nullable<Int32> hashCode; 

    public virtual Guid Id { get; protected set; } 
    public virtual Byte[] Version { get; set; } 

    public override Boolean Equals(Object obj) { 
     var other = obj as T; 
     if(other == null) { 
      return false; 
     } 

     var thisIsNew = Equals(this.Id, Guid.Empty); 
     var otherIsNew = Equals(other.Id, Guid.Empty); 

     if(thisIsNew && otherIsNew) { 
      return ReferenceEquals(this, other); 
     } 

     return this.Id.Equals(other.Id); 
    } // public override Boolean Equals(Object obj) { 

    public override Int32 GetHashCode() { 
     if(this.hashCode.HasValue) { 
      return this.hashCode.Value; 
     } 

     var thisIsNew = Equals(this.Id, Guid.Empty); 
     if(thisIsNew) { 
      this.hashCode = base.GetHashCode(); 
      return this.hashCode.Value; 
     } 
     return this.Id.GetHashCode(); 
    } // public override Int32 GetHashCode() { 

    public static Boolean operator ==(AbstractEntity<T> l, AbstractEntity<T> r) { 
     return Equals(l, r); 
    } 
    public static Boolean operator !=(AbstractEntity<T> l, AbstractEntity<T> r) { 
     return !Equals(l, r); 
    } 
} // public abstract class AbstractEntity<T>... 

由於所有components嵌套在entities我應該然後實現Equals()GetHashCode()又在哪裏?

+1

相關:http://stackoverflow.com/questions/371328/why-is-it-important-to-override-gethashcode-when-equals-method-is-overridden?rq=1 – 2013-04-11 11:17:33

回答

1

正確表示GetHashCode預期返回相同的哈希碼是相同的。因爲兩個實體的平等是通過比較這些代碼來實現的。

另一方面,這意味着對於不相同的實體,散列碼的唯一性必須爲,保證爲,儘可能多。

+0

這應該只應用於組件中的「組件」還是應用於域中的所有「組件」(「值對象」)? – lexeme 2013-04-11 11:05:01

+1

鑑於GetHashCode通常表示保真度的損失(即,在對象中編碼的數據多於在生成的32位散列中編碼的數據),所以不能保證不平等對象的散列碼的唯一性。埃爾戈,你的最後一點是不正確的。在散列中的碰撞是不可避免的(除非你散列的東西攜帶少於或等於32位的信息,並且你製作了一個完美的散列) – spender 2013-04-11 11:08:41

+0

它取決於你的應用的*邏輯*。所以邏輯是:make gethashcode爲* your *系統必須像equals一樣被識別的所有組件返回相同的值。例如:如果我看專家,醫生和司機是不平等的,如果從生物學的角度來看他們*是平等的(都是人類)。所以取決於* yuor應用程序應該如何工作。 – Tigran 2013-04-11 11:09:27

1

EqualsGetHashCode的文檔很好地解釋了這一點,幷包含了關於值對象實現的具體指導。對於值對象,如果對象是相同類型並且公共和私有字段相等,則等於true。但是,這種解釋適用於框架值類型,您可以通過覆蓋它來自由創建自己的Equals。

的GetHashCode有兩個規則必須遵循:

  • 如果兩個對象的比較結果爲相等,爲每個對象GetHashCode方法必須返回相同的值。但是,如果兩個對象 的比較結果不相等,則兩個對象的GetHashCode方法不需要 必須返回不同的值。

  • 只要對對象狀態 沒有修改來確定對象的Equals方法的返回值,對象的GetHashCode方法就必須始終返回相同的哈希代碼。注意 這僅適用於應用程序的當前執行 ,並且如果應用程序再次運行 ,則可以返回不同的散列碼。