35

测试该Equals方法非常简单(据我所知)。但是你到底是如何测试这个GetHashCode方法的呢?

4

7 回答 7

42

测试两个不同的相等的对象是否具有相同的哈希码(对于不同的值)。检查不相等的对象是否给出不同的哈希码,一次改变一个方面/属性。虽然哈希码不必不同,但如果您为碰巧给出相同哈希码的属性选择不同的值,除非您有错误,否则您真的很不幸。

于 2009-11-08T15:37:25.767 回答
10

Gallio/MbUnit v3.2带有方便的合约验证器,能够测试您的GetHashCode()IEquatable<T>. 更具体地说,您可能对EqualityContract和感兴趣HashCodeAcceptanceContract。有关更多详细信息,请参见此处此处此处

public class Spot
{
  private readonly int x;
  private readonly int y;

  public Spot(int x, int y)
  {
    this.x = x;
    this.y = y;
  }

  public override int GetHashCode()
  {
    int h = -2128831035;
    h = (h * 16777619) ^ x;
    h = (h * 16777619) ^ y;
    return h;
  }
}

然后你像这样声明你的合约验证者:

[TestFixture]
public class SpotTest
{
  [VerifyContract]
  public readonly IContract HashCodeAcceptanceTests = new HashCodeAcceptanceContract<Spot>()
  {
    CollisionProbabilityLimit = CollisionProbability.VeryLow,
    UniformDistributionQuality = UniformDistributionQuality.Excellent,
    DistinctInstances = DataGenerators.Join(Enumerable.Range(0, 1000), Enumerable.Range(0, 1000)).Select(o => new Spot(o.First, o.Second))
  };
}
于 2010-05-19T12:31:14.970 回答
5

它与 Equals() 非常相似。您需要确保两个“相同”的对象至少具有相同的哈希码。这意味着如果 .Equals() 返回 true,则哈希码也应该相同。至于正确的哈希码值是什么,这取决于您如何进行哈希处理。

于 2009-11-08T15:38:01.770 回答
3

从个人经验。除了像相同的对象给您相同的哈希码这样显而易见的事情之外,您还需要创建足够大的唯一对象数组并计算其中的唯一哈希码。如果唯一的哈希码少于总对象数的 50%,那么你就有麻烦了,因为你的哈希函数不好。

        List<int> hashList = new List<int>(testObjectList.Count);
        for (int i = 0; i < testObjectList.Count; i++)
        {
            hashList.Add(testObjectList[i]);
        }

        hashList.Sort();
        int differentValues = 0;
        int curValue = hashList[0];
        for (int i = 1; i < hashList.Count; i++)
        {
            if (hashList[i] != curValue)
            {
                differentValues++;
                curValue = hashList[i];
            }
        }

        Assert.Greater(differentValues, hashList.Count/2);
于 2009-11-08T16:12:36.257 回答
0

我会预先提供一个已知/预期的哈希并比较 GetHashCode 的结果。

于 2009-11-08T15:36:57.803 回答
0

您创建具有相同值的单独实例并检查实例的 GetHashCode 是否返回相同的值,以及对同一实例的重复调用是否返回相同的值。

这是哈希码工作的唯一要求。为了正常工作,哈希码当然应该有一个良好的分布,但是测试需要大量的测试......

于 2009-11-08T15:40:50.980 回答
0

除了检查对象相等是否意味着哈希码相等,并且按照 Yann Trevin 的建议,哈希的分布相当平坦(如果性能是一个问题),您可能还希望考虑如果您更改对象的属性会发生什么。

假设您的对象在字典/哈希集中时发生了变化。您是否希望 Contains(object) 仍然为真?如果是这样,那么您的 GetHashCode 最好不要依赖于已更改的可变属性。

于 2016-05-10T17:08:44.023 回答