Question C #: Comment testeriez-vous GetHashCode?


Tester le Equals la méthode est assez simple (pour autant que je sache). Mais comment testez-vous la GetHashCode méthode?


30
2017-11-08 15:34


origine


Réponses:


Testez que deux objets distincts égaux ont le même code de hachage (pour différentes valeurs). Vérifiez que les objets non égaux donnent des codes de hachage différents, en faisant varier un aspect / une propriété à la fois. Bien que les codes de hachage ne avoir pour être différent, vous seriez vraiment malchanceux de choisir des valeurs différentes pour les propriétés qui se produire pour donner le même code de hachage à moins d'avoir un bug.


33
2017-11-08 15:37



Gallio / MbUnit v3.2 est livré avec des vérificateurs de contrat pratiques qui sont en mesure de tester votre implémentation de GetHashCode() et IEquatable<T>. Plus précisément, vous pouvez être intéressé par le EqualityContract et le HashCodeAcceptanceContract. Voir ici, ici et  pour plus de détails.

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

Ensuite, vous déclarez votre vérificateur de contrat comme ceci:

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

9
2018-05-19 12:31



Ce serait assez similaire à Equals (). Vous voulez vous assurer que deux objets "identiques" ont au moins le même code de hachage. Cela signifie que si .Equals () renvoie true, les codes de hachage doivent également être identiques. En ce qui concerne les valeurs de hashcode appropriées, cela dépend de la façon dont vous avez haché.


5
2017-11-08 15:38



De l'expérience personnelle. Mis à part les choses évidentes, comme les mêmes objets vous donnant les mêmes codes de hachage, vous devez créer un tableau suffisamment grand d'objets uniques et compter parmi eux des codes de hachage uniques. Si des codes de hachage uniques font moins de, disons 50% du nombre total d'objets, vous êtes en difficulté, car votre fonction de hachage n'est pas bonne.

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

3
2017-11-08 16:12



Je pré-fournirais un hachage connu / attendu et comparerais le résultat de GetHashCode.


0
2017-11-08 15:36



Vous créez des instances distinctes avec la même valeur et vérifiez que GetHashCode pour les instances renvoie la même valeur et que les appels répétés sur la même instance retournent la même valeur.

C'est la seule exigence pour qu'un code de hachage fonctionne. Pour bien fonctionner, les codes de hachage devraient bien sûr avoir une bonne distribution, mais cela demande beaucoup de tests ...


0
2017-11-08 15:40



En plus de vérifier que l'égalité des objets implique l'égalité des codes de hachage et que la distribution des hachages est assez plate comme suggéré par Yann Trevin (si les performances sont préoccupantes), vous pouvez également envisager ce qui se passe si

Supposons que votre objet change pendant qu'il se trouve dans un dictionnaire / hashset. Voulez-vous que le Contains (objet) soit toujours vrai? Si tel est le cas, il est préférable que votre GetHashCode ne dépende pas de la propriété mutable qui a été modifiée.


0
2018-05-10 17:08