2013-05-15 28 views
1

我有我已經實現IEquatable<T>這樣一個類的對象平等的測試集合,當我測試,我可以用一個調用,如輕鬆地比較這些對象的IEnumerable集合:使用IEquatable <T>

Assert.IsTrue(expected.SequenceEqual(actual)); 

這是目前運作良好,但我有一些嘮叨的疑慮。這個類看起來是這樣的:

public class ThirdPartyClaim : IEquatable<ThirdPartyClaim> 
{ 
    // fields removed for question 

    public bool Equals(ThirdPartyClaim compareTo) 
    { 
     if (object.ReferenceEquals(this, compareTo)) 
     { 
      return true; 
     } 

     return this.ClaimId.Equals(compareTo.ClaimId) && 
       this.Firstname.Equals(compareTo.Firstname) && 
       this.Lastname.Equals(compareTo.Lastname); 
    } 

    public override int GetHashCode() 
    {  
     int hashClaimId = this.ClaimId == null ? 0 : this.ClaimId.GetHashCode(); 
     int hashFirstname = this.Firstname == null ? 0 : this.Firstname.GetHashCode(); 
     int hashLastname = this.Lastname == null ? 0 : this.Lastname.GetHashCode(); 

     return hashClaimId^hashFirstname^hashLastname; 
    } 

我重寫GetHashCode()的理解是,它被用來比較指向類的同一個實例對象。在這種情況下(甚至在將來)這是非常不可能的。

這種理解是否正確,如果是的話,我可以安全地刪除代碼嗎?

有沒有更好的方法來比較我的單元測試中這些對象的集合?

儘管我受限於使用MSTest。

Thans

+1

不,'GetHashCode()'用於計算任何實例的哈希碼。在執行「等於」時使用的任何字段也應該用於計算哈希碼。 –

回答

4

重寫GetHashCode當你重寫Equals,否則基於散列的容器可能無法正常工作是必需的。從Object.Equals的文檔:

覆蓋Equals的類型還必須重寫GetHashCode;否則,Hashtable可能無法正常工作。

即使代碼在您的情況下可能不會被執行,您仍應保留它。除了是正確的,這將有助於不論其序列的你測試集的平等:

Assert.IsTrue(expected.Except(actual).Count() == 0);  

一個變化我會做給GetHashCode實現消除其對稱性:目前,圍繞第一個和最後一個名稱切換在你的對象內部會導致製作相同的哈希碼。這是次優的。您可以將多個int乘以一個小的素數(例如, 31,並將它們相加,如下所示:

public override int GetHashCode() 
{  
    int hashClaimId = this.ClaimId == null ? 0 : this.ClaimId.GetHashCode(); 
    int hashFirstname = this.Firstname == null ? 0 : this.Firstname.GetHashCode(); 
    int hashLastname = this.Lastname == null ? 0 : this.Lastname.GetHashCode(); 

    return 31*31*hashClaimId + 31*hashFirstname^hashLastname; 
}