使用equatable 测试对象集合是否相等

本文关键字:集合 是否 对象 测试 equatable 使用 | 更新日期: 2023-09-27 18:13:45

我有一个类,我已经实现了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.

谢谢

使用equatable <T>测试对象集合是否相等

在覆盖Equals时需要覆盖GetHashCode,否则基于散列的容器可能无法正常工作。来自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;
}