2017-02-01 9 views
0

Toutes les ressources montrant comment passer outre Equals(object) et GetHashCode() utiliser des champs numériques pour mettre en œuvre la méthode GetHashCode():Comment remplacer GetHashCode() sans aucun numéro en tant que champs?

Implementing the Equals Method
What's the best strategy for Equals and GetHashCode?
Why is it important to override GetHashCode when Equals method is overridden?

Cependant, dans ma classe, je n'ai pas numérique des champs. Il est un nœud dans un arbre avec une référence à ses parents, les enfants, et une interface que les données:

public class Node 
{ 
    private IInterface myInterface; 
    private Node parent; 
    private List<Node> children = new List<Node>(); 

    public override bool Equals(object obj) 
    { 
     if (obj == null || GetType() != obj.GetType()) 
     { 
      return false; 
     } 
     var node = (Node)obj; 
     return myInterface == node.myInterface; 
    } 

    public override int GetHashCode() 
    { 
     ??? 
    } 
} 

Que dois-je régler la hashcode avec?

Répondre

6

Selon Equals mise en œuvre, deux instances de Node sont égaux si et seulement si leur myInterface sont égaux:

public override bool Equals(object obj) 
{ 
    if (obj == null || GetType() != obj.GetType()) 
    { 
     return false; 
    } 
    var node = (Node)obj; 

    // instances are equal if and only if myInterface's are equal 
    return myInterface == node.myInterface; 
} 

C'est pourquoi myInterface est la seule source pour GetHashCode:

public override int GetHashCode() 
{ 
    return null == myInterface ? 0 : myInterface.GetHashCode(); 
} 

post-scriptum (Edité, grâce à Kris Vandermotten) Souvent, il est une bonne pratique pour vérifier ReferenceEquals dans la mise en œuvre Equals avant de comparer potentiellement le temps/consomme beaucoup de ressources myInterface s:

public override bool Equals(object obj) { 
    // Easy tests: 
    // 1. If "this" and "obj" are in fact just the same reference? 
    // 2. Since `Node` (or Equals) is not sealed, the safiest is to check types 
    if (object.ReferenceEquals(this, obj)) 
    return true; 
    else if (null == obj || other.GetType() != GetType()) 
    return false; 

    // Potentially time/resource cosuming (we don't know IInterface implementation) 
    return ((Node) obj).myInterface == myInterface; 
} 
+1

Votre méthode 'Equals' ne vérifie pas type égalité. A cause de cela, on pourrait argumenter que c'est correct seulement s'il n'y a aucun type qui hérite de 'Node'. Et si 'Node' est' public', cela signifie qu'il devrait être 'sealed'. En outre, mais c'est un problème distinct, j'implémenterais probablement également IEquatable , principalement pour des raisons de performance. –

+1

@Evorlor: 1. souvent c'est une bonne pratique de tester * l'égalité de référence * (instance égale à elle-même) avant de commencer à comparer myInterface (qui peut être le temps/ressources cosuming) 2. 'as' a été spécialement conçu pour de telles comparaisons; n'utilisez pas 'GetType' et cast dans ce cas. –

+0

@Kris Vandermotten: Je suis d'accord avec vous que l'implémentation de l'interface 'IEquatable ' est une * bonne idée *. Cependant, 'Equals' compare les noeuds (d'un graphe?), Pas les implémentations; si une classe dérivée 'MyNode' veut changer la politique, elle doit remplacer' Equals' et 'GetHashCode' –