Des éclaircissement sur les Comparer : Equals et surtout GetHashCode
Bonjour,
Afin d'utiliser entre autre, les méthodes Distinct, Except, Intersect de LINQ to Object, j'ai besoin d'utiliser les Comparer.
J'ai besoin d'éclaircissement sur les comparer.
Avant, j'utilisais des comparer simples en utilisant la clé primaire d'un objet.
J'ai pas trop cherché à comprendre le fonctionnement.
Ma classe 'CriteriaComparerPK' , permettant de comparer des objets 'Criteria' avec leur clé primaire 'idCriteria'
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class CriteriaComparerPK : IEqualityComparer<Criteria>
{
bool IEqualityComparer<Criteria>.Equals(Criteria x, Criteria y)
{
if (x == null || y == null) return false;
return (x.idCriteria == y.idCriteria);
}
int IEqualityComparer<Criteria>.GetHashCode(Criteria obj)
{
return obj.idCriteria.GetHashCode();
}
} |
Exemple d'utilisation du Comparer : exemple d'Intersect :
Code:
var listFinal = listCriteria1.Intersect(listCriteria2, new CriteriaComparerPK());
Jusqu'ici, en utilisant des comparer sur clé primaire, ça fonctionnait bien.
Mais récemment j'ai eu plus de difficultés à faire un comparer sur un objet n'ayant pas de PK (clé primaire).
Du coup j'aimerais bien comprendre un peu plus en détails le fonctionnement des comparers.
Mon objet à 3 propriétés.
pte1, pte2 et pte3.
Cet objet n'a pas de clé primaire dans mon scénario, donc je suis obligé de comparer les champs un à un pour différencier deux objets de ce type.
En sachant en plus que pte3 peut soit être renseignée, soit null.
Ex :
Un objet o1 { pte1 = "toto", pte2="tata", pte3=3 }
doit être différent d'un objet o2 { pte1 = "toto", pte2="tata", pte3=null }
Après plusieurs essais non concluants, j'ai fini par écrire mon comparer pour cet objet comme ceci :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class MyObjectComparerThreeProperties : IEqualityComparer<MyObject>
{
bool IEqualityComparer<MyObject>.Equals(MyObject x, MyObject y)
{
if (x == null || y == null) return false;
return Equals(x.pte1, y.pte1) && Equals(x.pte2, y.pte2) && Equals(x.pte3, y.pte3);
}
int IEqualityComparer<MyObject>.GetHashCode(MyObject obj)
{
return obj.pte1.GetHashCode();
}
} |
Mes questions sont les suivantes :
1)J'ai toujours pensé que le GetHashCode devait renvoyer un résultat différent pour des objets différents.
On m'a appris il y a pas lgtps que ce n'est pas vrai : 2 objets différents pourraient renvoyer le même résultat pour GetHashCode.
=> C'est ce point en particulier qui me posait problème car j'essayer de gérer la propriété nullable dans GetHashCode.
J'avais déjà rencontré des cas où, quand je mettais un GetHascode renvoyant un resultat identique pour des objet différents, mon comparer ne fonctionnait pas bien. J'en ai donc déduit que pour fonctionner correctement, la fonction GetHashCode d'un comparer devait renvoyer, une valeur différente pour des objets différents. Mais apparemment, cette supposition est fausse.
Est ce que c'est vrai ?
2) Est ce que mon Comparer vous semble correct ?
Est ce qu'il gère bien ma propriété3 qui peut être null ? Pas d'exception ?