我有一个类,我已经实现了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。
Thans
答案 0 :(得分: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;
}