C # différence entre == et égal à ()
Question
J'ai une condition dans une application silverlight qui compare deux chaînes. Pour une raison quelconque, lorsque j'utilise ==
, il renvoie false avec .Equals ()
renvoie true .
Voici le code:
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content.Equals("Energy Attack"))
{
// Execute code
}
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
// Execute code
}
Avez-vous une raison de le faire?
La solution
Lorsque ==
est utilisé sur une expression de type objet
, la résolution est System.Object.ReferenceEquals
.
est égal à
est simplement un < code> virtual et se comporte comme tel, la version remplacée sera donc utilisée (qui, pour le type string
compare le contenu).
Autres conseils
Lors de la comparaison d'une référence d'objet à une chaîne (même si la référence d'objet fait référence à une chaîne), le comportement spécial de l'opérateur ==
spécifique à la classe de chaîne est ignoré.
Normalement (lorsqu'il ne s'agit pas de chaînes, c'est-à-dire), est égal à
compare les valeurs , tandis que ==
compare les références d'objet .
Si deux objets que vous comparez font référence à la même instance exacte d'un objet, ils renverront tous les deux la valeur true, mais si l'un d'entre eux a le même contenu et provient d'une source différente (est une instance séparée avec les mêmes données), seul Equals retourne vrai. Cependant, comme indiqué dans les commentaires, chaîne constitue un cas particulier, car elle remplace l'opérateur ==
. Ainsi, lorsqu'il s'agit uniquement de références de chaîne (et non de références d'objet), seules les valeurs sont comparées, même si sont des instances séparées. Le code suivant illustre les différences subtiles dans les comportements:
string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));
Le résultat est:
True True True
False True True
False False True
==
et .Equals
dépendent tous deux du comportement défini dans le type réel et du type réel sur le site d'appel. Les deux ne sont que des méthodes / opérateurs qui peuvent être remplacés par tout type et tout comportement souhaité par l'auteur. D'après mon expérience, il est courant que les gens implémentent .Equals
sur un objet, mais négligent d'implémenter l'opérateur ==
. Cela signifie que .Equals
va réellement mesurer l’égalité des valeurs tandis que ==
va mesurer si elles sont ou non la même référence.
Lorsque je travaille avec un nouveau type dont la définition est en train de changer ou d'écrire des algorithmes génériques, je trouve que la meilleure pratique est la suivante
- Si je veux comparer des références en C #, j'utilise directement
Object.ReferenceEquals
(inutile dans le cas générique) - Si je souhaite comparer des valeurs, j'utilise
EqualityComparer < T > .Default
Dans certains cas, lorsque je pense que l'utilisation de ==
est ambiguë, j'utiliserai explicitement Object.Reference
dans le code pour supprimer cette ambiguïté.
Eric Lippert a récemment publié un article sur son blog expliquant pourquoi il existe deux méthodes d’égalité dans le CLR. Ça vaut le coup de lire
Tout d'abord, il y a une une différence. Pour les chiffres
> 2 == 2.0
True
> 2.Equals(2.0)
False
Et pour les chaînes
> string x = null;
> x == null
True
> x.Equals(null)
NullReferenceException
Dans les deux cas, ==
se comporte mieux que .Equals
J'ajouterais que si vous convertissez votre objet en chaîne, celui-ci fonctionnera correctement. C’est pourquoi le compilateur vous avertit:
Comparaison de référence involontaire possible; pour obtenir une comparaison de valeur, lancer le côté gauche pour taper 'chaîne'
== Opérateur 1. Si les opérandes sont Types de valeur et que leurs valeurs sont égales, le résultat est renvoyé. vrai sinon faux. 2. Si les opérandes sont Types de référence à l'exception de chaîne et font référence à même objet, il retourne vrai sinon faux. 3. Si les opérandes sont de type chaîne et que leurs valeurs sont égales, la valeur renvoyée est true sinon false.
.Equals 1. Si les opérandes sont des types de référence, il effectue une égalité de référence si tous deux se réfèrent au même objet, il retourne true sinon false. 2. Si les opérandes sont des types de valeur, alors, contrairement à l'opérateur ==, il vérifie d'abord leur type et si leur type est identique, il exécute l'opérateur ==, sinon il renvoie false.
Pour autant que je sache, la réponse est simple:
- == compare les références d'objet.
- .Equals compare le contenu de l'objet.
- Les types de données de chaîne agissent toujours comme une comparaison de contenu.
J'espère avoir raison et qu'il a répondu à votre question.
La version statique de la méthode .Equal
n'ayant pas été mentionnée jusqu'à présent, j'aimerais l'ajouter ici pour résumer et comparer les 3 variantes.
MyString.Equals("Somestring")) //Method 1
MyString == "Somestring" //Method 2
String.Equals("Somestring", MyString); //Method 3 (static String.Equals method) - better
où MyString
est une variable qui provient d'un autre endroit du code.
Informations de base et résumé:
En Java, l'utilisation de ==
pour comparer des chaînes ne doit pas être utilisée. Je le mentionne au cas où vous devriez utiliser les deux langues et aussi
pour vous informer que l'utilisation de ==
peut également être remplacée par quelque chose de meilleur en C #.
En C #, il n'y a pas de différence pratique pour comparer des chaînes à l'aide de la Méthode 1 ou de la Méthode 2 tant que les deux sont de type chaîne. Cependant, si l'une est nulle, si elle est d'un autre type (comme un entier) ou si elle représente un objet ayant une référence différente, alors, comme le montre la question initiale, vous pouvez vous rendre compte que la comparaison du contenu pour l'égalité ne renvoie pas ce que vous vous attendez.
Solution suggérée:
Parce que l'utilisation de ==
n'est pas exactement la même chose que d'utiliser .Equals
lors de la comparaison d'éléments, vous pouvez utiliser la méthode static String.Equals . au lieu. De cette façon, si les deux côtés ne sont pas du même type, vous comparerez quand même le contenu et si l'un d'entre eux est null, vous éviterez l'exception.
bool areEqual = String.Equals("Somestring", MyString);
C’est un peu plus écrit, mais à mon avis plus sûr à utiliser.
Voici quelques informations copiées à partir de Microsoft:
public static bool Equals (string a, string b);
Paramètres
une
chaîne
La première chaîne à comparer, ou null
.
b
Chaîne
La deuxième chaîne à comparer, ou null
.
Renvoie Boolean
true
si la valeur de a
est identique à la valeur de b
; sinon, false
. Si a
et b
sont null
, la méthode retourne true
.
Je suis un peu confus ici. Si le type de contenu d'exécution est de type chaîne, alors == et Equals doivent renvoyer true. Toutefois, comme cela ne semble pas être le cas, le type de contenu d'exécution n'est pas une chaîne et l'appel d'Equal sur une égalité référentielle lui permet de réaliser une égalité référentielle, ce qui explique pourquoi Echals ("Energy Attack") échoue. Toutefois, dans le second cas, la décision relative à l'opérateur appelé == statique surchargé est prise au moment de la compilation et cette décision semble être == (chaîne, chaîne). cela me suggère que Content fournit une conversion implicite en chaîne.
Il y a une autre dimension à une réponse antérieure de @BlueMonkMN. La dimension supplémentaire est que la réponse à la question de titre de @ Drahcir, telle qu’elle est énoncée, dépend également de comment nous sommes arrivés à la valeur chaîne
. Pour illustrer:
string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
string s5 = "te" + "st";
object s6 = s5;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("\n Case1 - A method changes the value:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));
Console.WriteLine("\n Case2 - Having only literals allows to arrive at a literal:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s5), s1 == s5, s1.Equals(s5));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s6), s1 == s6, s1.Equals(s6));
Le résultat est:
True True True
Case1 - A method changes the value:
False True True
False False True
Case2 - Having only literals allows to arrive at a literal:
True True True
True True True
Ajouter un point de plus à la réponse.
La méthode .EqualsTo ()
vous permet de comparer la culture et la casse.
Juste comme un ajout aux bonnes réponses: ce comportement n'est PAS limité aux chaînes ou à la comparaison de différents types numériques. Même si les deux éléments sont de type objet du même type sous-jacent. " == " ne fonctionnera pas.
La capture d'écran suivante montre les résultats de la comparaison de deux valeurs {int} d'objet
Le jeton ==
en C # est utilisé pour deux opérateurs de vérification d'égalité différents. Lorsque le compilateur rencontre ce jeton, il vérifie si l'un des types comparés a implémenté une surcharge d'opérateur d'égalité pour les types de combinaison spécifiques comparés (*) ou pour une combinaison de types vers laquelle les deux types peuvent être convertis. Si le compilateur trouve une telle surcharge, il l'utilisera. Sinon, si les deux types sont tous deux des types de référence et qu'ils ne sont pas des classes sans rapport (soit une interface, soit des classes liées), le compilateur considérera ==
comme un opérateur de comparaison de références. . Si aucune des deux conditions ne s'applique, la compilation échouera.
Notez que d'autres langues utilisent des jetons distincts pour les deux opérateurs de contrôle d'égalité. Dans VB.NET, par exemple, le jeton =
est utilisé dans les expressions uniquement pour l'opérateur de contrôle d'égalité surchargeable, et Is
est utilisé en tant que test de référence ou null. opérateur de test. L'utilisation de =
sur un type qui ne remplace pas l'opérateur de vérification d'égalité échouera, de même que toute tentative d'utilisation de Is
à des fins autres que le test d'égalité ou de nullité de référence.
(*) Les types ne surchargent généralement que l'égalité pour la comparaison avec eux-mêmes, mais il peut être utile que les types surchargent l'opérateur d'égalité pour la comparaison avec d'autres types particuliers; Par exemple, int
pourrait avoir (et IMHO devrait mais ne l'a pas fait) défini des opérateurs d'égalité pour la comparaison avec float
, de sorte que 16777217 ne se signale pas comme étant égal à 16777216f. En l’état, puisqu’aucun opérateur de ce type n’est défini, C # promeut int
en float
, en l’arrondissant à 16777216f avant que l’opérateur de contrôle d’égalité ne le voie; cet opérateur voit ensuite deux nombres à virgule flottante égaux et les signale égaux, ignorant l'arrondi qui a eu lieu.
Vraiment d'excellentes réponses et exemples!
Je voudrais juste ajouter la différence fondamentale entre les deux,
Les opérateurs tels que
.==
ne sont pas polymorphes, alors queest égal à
est
Avec ce concept en tête, si vous travaillez sur un exemple (en regardant le type de référence gauche et droit, et en vérifiant / sachant si le type a réellement == opérateur surchargé et égal à être surchargé), vous êtes certain d'obtenir la bonne réponse.
Lorsque nous créons un objet, celui-ci comprend deux parties: le contenu et l’autre, une référence à ce contenu.
==
compare le contenu et la référence;
equals ()
compare uniquement le contenu
http: // www. codeproject.com/Articles/584128/What-is-the-difference-between-equalsequals-and-Eq
==
L'opérateur == peut être utilisé pour comparer deux variables de tout type. Il compare simplement les bits .
int a = 3;
byte b = 3;
if (a == b) { // true }
Remarque: il y a plus de zéros à gauche de l'int, mais on s'en fiche de ça ici.
int a (00000011) == octet b (00000011)
N'oubliez pas == l'opérateur se soucie uniquement de la structure des bits de la variable.
Utilisation == Si deux références (primitives) font référence au même objet sur le tas.
Les règles sont les mêmes, que la variable soit une référence ou une primitive.
Foo a = new Foo();
Foo b = new Foo();
Foo c = a;
if (a == b) { // false }
if (a == c) { // true }
if (b == c) { // false }
a == c est vrai a == b est faux
les configurations de bits sont les mêmes pour a et c, elles sont donc égales avec ==.
Equal ():
Utilisez la méthode equals () pour voir si deux objets différents sont égaux .
Par exemple, deux objets String différents représentant les caractères de "Jane"
.La seule différence entre Equal et == réside dans la comparaison du type d'objet. dans d'autres cas, tels que les types de référence et les types de valeur, ils sont presque identiques (les deux sont une égalité bit par bit ou les deux sont une égalité de référence).
objet: Égale: égalité au niveau des bits ==: égalité de référence
chaîne: (égal à == sont identiques pour chaîne, mais si l'une des chaînes est remplacée par objet, le résultat de la comparaison sera différent) Égale: égalité au niveau des bits ==: égalité au niveau des bits
Voir ici pour plus d'explications.