1

我有一个已经实现的类,IEquatable<T>以便在测试时可以IEnumerable使用以下调用轻松比较这些对象的集合:

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。

4

1 回答 1

4

覆盖GetHashCode时需要覆盖Equals,否则基于哈希的容器可能无法正常工作。从以下文档Object.Equals

覆盖 Equals 的类型也必须覆盖 GetHashCode;否则,Hashtable 可能无法正常工作。

即使代码可能不会在您的情况下得到执行,您还是应该保留它。除了正确之外,它还可以帮助您测试集合的相等性,而不管它们的顺序如何:

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

我将对实现进行的一个更改GetHashCode是消除其对称性:目前,在对象内切换名字和姓氏会导致生成相同的哈希码。这是次优的。您可以将多个ints 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;
}
于 2013-05-15T10:19:10.537 回答