2016-08-12 1 views
0

Pour la vie de ma personne, je n'arrive pas à faire en sorte que ma liaison WPF fonctionne correctement pour la propriété SelectedItem de RibbonComboBox.Equals override vs. IEquatable <>

Puis j'ai commencé à lire sur la façon dont .NET compare les éléments. Ma compréhension est que, dans certains cas, il compare le pointeur réel. Dans ce cas, charger une valeur nouvelle et égale à partir d'une base de données, par exemple, il peut ne pas être considéré comme égal. Alors j'ai commencé à chercher explicitement à mettre en œuvre Equals pour mon type. Cependant, cela semble un peu confus car il y a au moins deux versions différentes que je peux mettre en œuvre.

Le code ci-dessous montre que je peux soit surcharger object.Equals, soit implémenter IEquatable<>. En fait, le code ci-dessous implémente les deux, et les tests indiquent que sont tous les deux appelés.

public class TextValuePair : IEquatable<TextValuePair> 
{ 
    public string Text { get; set; } 
    public int Value { get; set; } 

    public override bool Equals(object obj) 
    { 
     if (obj == null || !(obj is TextValuePair)) 
      return false; 
     return Value == (obj as TextValuePair).Value; 
    } 

    public override int GetHashCode() 
    { 
     return Value; 
    } 

    public bool Equals(TextValuePair obj) 
    { 
     Debug.Assert(obj != null); 
     if (obj == null) 
      return false; 
     return Value == obj.Value; 
    } 
} 

Quelqu'un peut-il me aider à comprendre ce qui est nécessaire pour éviter mes objets d'être comparé à l'équivalence par les routines de la bibliothèque .NET en fonction de pointeurs ayant la même valeur? Est-il vraiment nécessaire d'implémenter les deux versions de Equals?

+0

Il existe de nombreuses façons possibles d'implémenter 'Equals', mais pourquoi ne choisissez-vous pas simplement' override Equals', car il sera toujours utilisé. Cela ne fonctionne-t-il pas dans votre cas? – meJustAndrew

+0

@meJustAndrew: Ma liaison a toujours des problèmes mais cela n'est probablement pas lié à ce stade. Puisque les deux versions de 'Equals' sont appelées, comment puis-je savoir que le remplacement est suffisant et sera toujours utilisé? Deux versions étant appelées sorte de feuilles je ne sais pas quand chacune sera appelée. –

+2

Voir: http://stackoverflow.com/questions/2734914/whats-the-difference-between-iequatable-and-just-overriding-object-equals – Arno

Répondre

2

Comme indiqué par msdn, si vous implémentez IEquatable<T> vous aurez toujours besoin de passer outre Equals parce qu'il sera toujours appelé avec la signature Equals(System.Object, System.Object) et override yhe doivent être compatibles avec les méthodes mises en œuvre à partir IEquatable<T>.

Comme dans le question about the difference between iequatable and just overriding object equals qu'Arno a montré dans le commentaire, IEquatable<T> est utilisé lorsque les opérations sur les collections sont nécessaires pour les optimiser, pour ne plus avoir besoin de la boxe, et appeler les équals directs avec le type spécifique.

Vous avez deux options:

Si vous êtes intéressé par les performances lorsque vous travaillez avec des collections dans votre programme, vous pouvez continuer d'appliquer les deux méthodes Equals;

ou

Vous pouvez simplement supprimer le IEquatable<T> et seulement remplacer Equals pour simplifier votre code.

En outre, chaque fois que vous remplacez Equals, vous devez toujours outrepasser GetHashCode.

+0

Oui, il semble que 'object.Equals()' soit le seul moyen de remplacer les comparaisons. Mais comme il nécessite des types de valeurs de boxe, le nouveau 'IEquatable <>' a été ajouté pour être plus rapide. Pour des raisons de performances, il semble que vous deviez implémenter les deux. Cependant, quand vous dites _it sera toujours appelé avec la signature Equals (System.Object, System.Object) _, savez-vous dans quel cas cette version est appelée? –

+0

@JonathanWood C'est une bonne question aussi, elle sera appelée si vous faites 'Object.Equals (objectA, objectB)', où ceci pourrait être encadré par différents types, et ils peuvent toujours être égaux, pour un override Equals donné et s'ils ont les mêmes propriétés. – meJustAndrew