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