c# - 使用 IEquatable<T> 测试对象集合的相等性

标签 c# tdd gethashcode iequatable

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

谢谢

最佳答案

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

Types that override Equals must also override GetHashCode; otherwise, Hashtable might not work correctly.

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

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;
}

关于c# - 使用 IEquatable<T> 测试对象集合的相等性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16562307/

相关文章:

c# - 隐式类型和 TDD

testing - nodejs,文件更改时自动运行测试

c# - 在 GetHashCode 实现中处理集合

c# - 如何挑选质数来计算哈希码?

c# - 我应该如何实现 IEqualityComparer<T>.Equals

c# - EF Core 在调用中获取字符串的一部分

c# - 多线程程序中key个数固定的情况下用Dictionary代替ConcurrentDictionary是否可以?

c# - Linq-to-SQL 的开销

testing - 如何使用 RSpec 检查页面中有多少个特定的 HTML 元素?

unit-testing - 具有功能测试的用户界面 (UI) 的测试驱动开发 (TDD)