Comment vous la savez surement, pour comparer deux objets entre eux, vous pouvez utiliser l’opérateur « == » ou bien la méthode Equals().
Les deux existent et ne font pas toujours la même chose. Je vous propose de décortiquer un peu le comportement entre les deux solutions.
L’objectif de cet article est de vous aider à comprendre et à choisir la bonne méthode.
L’opérateur == est défini par défaut comme opérateur de comparaison des références.
La méthode Equals() est définie dans la classe System.Object. Tous les types vont donc en hériter. Certaines classes vont surcharger le comportement.
Nous allons voir cela de plus prêt.
L’opérateur == ou la méthode Equals
Par défaut, dans la classe Object, les deux font la même chose.
L’opérateur == va permettre de comparer les références entre deux objets.
La méthode Equals() va faire la même chose.
Ce qu’il est important de comprendre, c’est que dans la plupart des cas, la méthode Equals() va être surchargée dans les classes.
En effet, Equals() est/doit être utilisée pour comparer la valeur de l’objet (son contenu) et non pas la référence.
La classe String, par exemple, surcharge Equals() pour effectuer une comparaison (des caractères).
Je vous propose un exemple de code pour mieux comprendre :
[csharp] string str1 = "Une chaine";// création d’une deuxième chaine d’une autre manière
// pour éviter les optimisations du compilateur
string str2 = new string(
new char[] {
‘U’, ‘n’, ‘e’, ‘ ‘, ‘c’, ‘h’, ‘a’, ‘i’, ‘n’, ‘e’
});
// comparaison en utilisant == et Equals de la class String
Console.WriteLine(str1 == str2); // True
Console.WriteLine(str1.Equals(str2)); // True
object obj1 = str1;
object obj2 = str2;
// comparaison en utilisant == et Equals de la class Object
Console.WriteLine(obj1 == obj2); // False
Console.WriteLine(obj1.Equals(obj2)); // True
[/csharp]
Dans cet exemple, je construis deux chaines de caractères. Pour la deuxième, j’utilise un autre constructeur pour éviter l’optimisation par défaut du compilateur (sinon il aurait « stocké » une seule chaine dans votre exécutable et aurait affecté la même référence à str1 et à str2).
Le premier appel utilise == et retourne True. Cet opérateur est surchargé dans la classe String (la documentation indique clairement que l’opérateur va comparer le contenu de la chaine).
Le second appel utilise Equals() et retourne True également. Equals() compare le contenu (qui est le même pour les deux chaines).
Dans le troisième appel, == est appliqué sur un objet du type Object. Il n’y a donc pas de surcharge de l’opérateur et le compilateur va donc utiliser le comportement par défaut : comparer les références des deux objets obj1 et obj2. Cela retourne donc False car les références ne sont pas les mêmes.
Dans le quatrième appel, Equals() est appelée. Il s’agit d’une méthode virtuelle (surchargée dans la classe String). En réalité, .NET va donc appeler la méthode String.Equals() qui effectue une comparaison du contenu de la chaîne. Cela va donc retourner True comme dans le second appel.
Ok, alors comment choisir entre == ou Equals ?
Lorsque vous souhaitez comparer les références, il faudra toujours utiliser ==.
Lorsque vous souhaitez comparer le contenu d’un objet, il faudra utiliser la méthode Equals(). La classe comparée devra aussi proposer une surcharge de Equals sinon vous allez simplement comparer les références.
L’exception sera la classe String puisque == et Equals ont le même résultat (si les deux éléments comparés sont du type String).
[magicactionbox id= »3396″]
Thibaud says
Dans certains cas, ‘ReferenceEquals’ est plus explicite et évite les ambiguïtés car il ne peut pas être surchargé par les sous-classes : http://msdn.microsoft.com/en-us/library/system.object.referenceequals(v=vs.110).aspx
Pascal Lacroix says
Merci Thibaud.
Effectivement, c’est une solution qui permet d’être certain de bien comparer les références.
Car comme vous le dites, l’opérateur « == » pourrait être surchargé.