C# différence entre == et Equals()
J'ai une condition dans une application silverlight qui compare 2 chaînes, pour quelque raison que quand j'utilise ==
il retourne faux tout .Equals()
retourne vrai.
Voici le code:
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content.Equals("Energy Attack"))
{
//Execute code
}
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
//Execute code
}
Aucune raison pour expliquer pourquoi ce qui se passe?
- Voir aussi: stackoverflow.com/questions/144530/or-equals
- Chaîne remplace
==
, mais les opérateurs ne sont pas polymorphes. Dans ce code, le==
opérateur est appelé sur un typeobject
, qui effectue une identité comparaison au lieu d'une valeur. - Pour développer sur @DrewNoakes commentaire: Le compilateur choisit un
==
surcharge basée sur le type de compilation des opérandes. LeContent
propriété estobject
. Les opérateurs ne sont pas virtuels, de sorte que le défaut de mise en œuvre de==
est appelé, en donnant une référence de comparaison d'égalité. Avec égal à Égal, l'appel à la méthode virtuelleobject.Equals(object)
;string
remplace cette méthode et effectue une comparaison ordinale sur la chaîne de contenu. Voir msdn.microsoft.com/en-us/library/fkfd9eh8(v=vs. 110).aspx et referencesource.microsoft.com/#mscorlib/system/string.cs,507. - l'explication est précis. Il convient de noter que lorsque la gauche de
==
a le type de compilationobject
et le côté droit est le type de compilationstring
, alors le compilateur C# devez choisir le (problématique, dans ce cas) surchargeoperator ==(object, object)
; mais il va question au moment de la compilation d'avertissement qu'il pourrait être involontaire. Lisez donc le moment de la compilation des avertissements! Pour résoudre le problème et toujours utiliser==
, la fonte de la gauche àstring
. Si je me souviens bien, le texte de l'avertissement suggère juste que. - pour les conseils de lire les avertissements du compilateur. Encore mieux: activer les avertissements comme des erreurs option pour forcer tout le monde à prêter attention à eux.
Vous devez vous connecter pour publier un commentaire.
Quand
==
est utilisé sur une expression de typeobject
, il va se résoudre àSystem.Objet.ReferenceEquals
.Equals
est juste unvirtual
méthode et se comporte en tant que tel, de sorte que la version de remplacement sera utilisé (qui, pourstring
type compare le contenu).object
type (avis de la police à espacement fixe) est techniquement conçues pour être "une expression de typeSystem.Object
". Il n'a rien à voir avec le runtime type de l'instance qui est désigné par l'expression. Je pense que l'énoncé "défini par l'utilisateur opérateurs sont traités comme desvirtual
méthodes" est extrêmement trompeur. Ils sont traités comme des méthodes surchargées et ne dépendent que le moment de la compilation du type des opérandes. En fait, après l'ensemble des candidats définis par l'utilisateur opérateurs est calculée, le reste de la procédure de liaison sera exactement la surcharge de la méthode de résolution de l'algorithmepublic static operator ==(object a, Foo b){...}
ou que ce soit, mais la surcharge des opérateurs reste essentiellement très similaire à la surcharge de méthodes.virtual
méthode de résolution dépend de la réelle de l'exécution type de l'instance, alors que c'est complètement ignorée dans l'opérateur de résolution de surcharge, et c'est en effet le point de l'ensemble de ma réponse.string a = String.Copy("xyz"), b = String.Copy("xyz"); Console.WriteLine(String.ReferenceEquals(a,b)); Console.WriteLine(a==b);
impressionfalse
puistrue
. Semble==
est commeEquals
pourstring
?string
type. Essayez:Console.WriteLine((object)a == (object)b)
oùa
etb
sont des chaînes de caractères et le résultat sera le même queReferenceEquals
. De même, si vous avez déclaré une surcharge==
opérateur dans votre propre type, vous pouvez imiter le même comportement destring
.string str = "Hello";
), que "Bonjour" instance est conservé quelque part dans la mémoire, et plus loin "Bonjour" littéraux de chaîne ne sera pas de créer de nouvelles instances - il référence à l'instance dans la mémoire. C'est exactement pourquoi==
fonctionne pour la plupart des cas. Les choses commencent à se détraquer lorsque vous avez stringbuilders de l'INTERFACE et de textes.(string) == (string)
, ce qui signifieString
s surcharge de==
est utilisé. Cette surcharge se comporte comme prévu. Ce est la raison pour==
"fonctionne dans la plupart des cas". Même si deux objets string avec le même contenu sont comparés. Dans la question en cours de discussion, l'expression types sont(object) == (string)
. Cela provoque de l'objet==
à être utilisé, comme Mehrdad dit dans sa réponse.(object)
plutôt que de type(string)
.E.g. prendre deux chaînes, de les stocker dans des variables déclaréesobject
, puis de comparer ces deux variables. Dans cette situation, il compile àobject.==
, qui est mis en œuvre comme ReferenceEquals. Il en sera de n'est vrai que si c'est la même instance.Lors de la comparaison d'un objet de référence à une chaîne de caractères (même si l'objet de référence se réfère à une chaîne de caractères), le comportement de la
==
opérateur spécifique à la classe string est ignoré.(À condition de ne pas traiter avec les chaînes, qui est),
Equals
compare valeurs, tandis que==
compare les références de l'objet.Si deux objets sont en comparant font référence à la même instance d'un objet, puis les deux renvoie la valeur true, mais si on a le même contenu et est venu à partir d'une source différente (est une instance séparée avec les mêmes données), seulement Égale retournera true. Toutefois, comme indiqué dans les commentaires, la ficelle est un cas particulier, car il remplace le
==
de l'opérateur, de sorte que lorsque vous traitez uniquement avec chaîne de références (et pas les références de l'objet), seules les valeurs sont comparées, même si elles sont des instances distinctes. Le code suivant illustre les différences subtiles dans les comportements:La sortie est:
object.ReferenceEquals(s1, s3) == false
. Pourquoi?Substring
ne produit pas de nouvelle chaîne indépendants (qui 'll être interné & faire cette comparaison ==true
)? Faut-il utiliser chaîne d'origine de l'objet en quelque sorte (f.e. de retour de ref avec le start & données de fin)?==
et.Equals
sont à la fois dépendant du comportement défini le type réel et le type réel sur le site d'appel. Les deux sont tout simplement des méthodes /opérateurs qui peuvent être remplacés sur n'importe quel type et compte tenu de tout comportement de l'auteur le désire. Dans mon expérience, je trouve que c'est commun pour les gens à mettre en œuvre.Equals
sur un objet, mais de la négligence à mettre en œuvre opérateur==
. Cela signifie que.Equals
sera réellement mesurer l'égalité des valeurs, tout en==
permettra de mesurer si oui ou non ils sont de la même référence.Quand je travaille avec un nouveau type dont la définition est dans le flux ou l'écriture des algorithmes génériques, je trouve que la meilleure pratique est la suivante
Object.ReferenceEquals
directement (pas nécessaire dans le cas générique)EqualityComparer<T>.Default
Dans certains cas, quand je sens que l'utilisation de
==
est ambigu, je vais utiliser explicitementObject.Reference
égaux dans le code pour supprimer l'ambiguïté.Eric Lippert a récemment fait un post de blog sur le sujet de pourquoi il y a 2 méthodes de l'égalité dans la CLR. Il vaut la peine de le lire
Tout d'abord, il y est une différence. Pour les numéros de
Et pour les chaînes
Dans les deux cas,
==
se comporte de façon plus utile que.Equals
==
opérateur à être une bonne chose. Par exemple, si 16777216.0 f égal à (int)16777217, (double)16777217.0, les deux, ou aucun des deux? Les comparaisons entre les types intégraux sont beaux, mais à virgule flottante les comparaisons doivent être effectuées uniquement à mon humble avis avec les valeurs qui sont explicitement exprimés à l'appariement des types. La comparaison d'unfloat
à autre chose qu'à unfloat
, ou undouble
à autre chose qu'à undouble
, m'apparaît comme l'un des principaux odeur de code qui ne devrait pas compiler sans diagnostic.x == y
n'implique pasx/3 == y/3
(essayezx = 5
ety = 5.0
)./
pour la division entière d'être un défaut dans la conception de C# et Java. Pascaldiv
et même VB.NET's` are much better. The problems with
==` est pire, cependant:x==y
ety==z
n'implique pas quex==z
(considérer les trois numéros dans mon commentaire précédent). Comme pour la relation que vous suggérer, même six
ety
sont à la foisfloat
ou les deuxdouble
,x.equals((Object)y)
n'implique pas que1.0f/x ==
1.0 f/y` (si j'avais tenait qu'à moi, il serait garantie que, même si==
ne fait pas de distinction positive et zéro,Equals
devrait).Opérateur = =
1. Si les opérandes sont des Types De Valeur et leurs valeurs sont égales, elle renvoie true, sinon false.
2. Si les opérandes sont des Les Types De Référence à l'exception de la chaîne et les deux se réfèrent au même objet, elle renvoie true, sinon false.
3. Si les opérandes sont de type chaîne de caractères et leurs valeurs sont égales, elle renvoie true, sinon false.
.Est égal à
1. Si les opérandes sont des Types Référence, il effectue Référence De L'Égalité c'est si les deux font référence au même objet, elle renvoie true, sinon false.
2. Si les Opérandes sont des Types de Valeur alors contrairement à l'opérateur==, il vérifie pour leur type d'abord, et Si leurs types sont les mêmes qu'il effectue opérateur == sinon elle retourne false.
==
opérateur peut être surchargé pour n'importe quel type, pas seulement de la chaîne. Décrivant un cas d'exception que pour la chaîne dénature l'opérateur sémantique. Il serait plus exact, mais peut-être pas très utile, pour dire: "si les opérandes sont des types référence, il renvoie la valeur true si l'opérande font référence au même objet, sauf s'il existe une surcharge applicable, auquel cas la mise en œuvre de la surcharge détermine le résultat". Le même est vrai pourEquals
avec la complication supplémentaire que c'est une méthode virtuelle, de sorte que son comportement peut être remplacée ainsi que surchargé.Je voudrais ajouter que si vous lancez un objet à une chaîne alors qu'il fonctionne correctement. C'est pourquoi le compilateur va vous donner un avertissement en disant:
object expr = XXX; if (expr == "Energy") { ... }
, puis depuis la gauche, c'est de le type de compilationobject
, le compilateur doit utiliser la surchargeoperator ==(object, object)
. Il vérifie la référence à l'égalité. Si cela va donnertrue
oufalse
peut être difficile à prévoir en raison de string stage. Si vous savoir de la gauche, c'est soitnull
ou de typestring
, la fonte de la gauche àstring
avant d'utiliser==
.Aussi loin que je comprends bien la réponse est simple:
==
compare les références de l'objet..Equals
compare le contenu de l'objet.String
types de données toujours agir comme contenu de la comparaison.J'espère que je suis correct et que ça répond à votre question.
Parce que la version statique de la
.Equal
méthode n'a pas été mentionné jusqu'à présent, je tiens à ajouter ici de résumer et de comparer les 3 variantes.où
MyString
est une variable qui vient de quelque part d'autre dans le code.Informations de fond et pour résumer:
En Java à l'aide de
==
pour comparer des chaînes de caractères ne doit pas être utilisé. Je parle de cela dans le cas où vous avez besoin d'utiliser les deux langues et aussipour vous laisser savoir que l'utilisation de
==
peut également être remplacé par quelque chose de mieux en C#.En C# il n'y a pas de différence pratique pour comparer des chaînes de caractères à l'aide de la Méthode 1 ou la Méthode 2 tant que les deux sont de type string. Cependant, si l'on est nul, on est d'un autre type (comme un entier), ou l'un représente un objet qui a une référence différente, ensuite, que la question initiale, vous pouvez rencontrer qu'à comparer le contenu de l'égalité ne peut pas revenir sur ce que vous attendez.
Solution suggérée:
Parce que l'utilisation de
==
n'est pas exactement la même que l'utilisation de.Equals
lorsque l'on compare les choses, vous pouvez utiliser le statique de la Chaîne.Est égal à méthode à la place. De cette façon, si les deux parties ne sont pas du même type, vous aurez toujours comparer le contenu et si l'on est null, ce qui vous évitera de l'exception.C'est un peu plus à écrire, mais à mon avis, plus sûr à utiliser.
Voici quelques informations copiées à partir de Microsoft:
Paramètres
a
ChaîneLa première chaîne à comparer, ou
null
.b
ChaîneLa deuxième chaîne à comparer, ou
null
.Retourne
Boolean
true
si la valeur dea
est la même que la valeur deb
; sinon,false
. Si les deuxa
etb
sontnull
, la méthode renvoietrue
.Je suis un peu confus ici. Si le moteur d'exécution type de Contenu est de type chaîne de caractères, puis les deux == égalité et doit retourner true. Cependant, puisque cela ne semble pas être le cas, l'exécution type de Contenu n'est pas de la chaîne et l'appel est Égale à elle est en train de faire un référentiel de l'égalité et c'est ce qui explique pourquoi Equals("l'Attaque de l'Énergie") échoue. Cependant, dans le second cas, la décision quant à ce qui a surchargé == statique de l'opérateur doit être appelé en est faite au moment de la compilation et cette décision semble être ==(string,string). cela me suggère que le Contenu fournit une conversion implicite en chaîne.
Il y a une autre dimension à une précédente réponse par @BlueMonkMN. La dimension supplémentaire est que la réponse à la @Drahcir titre de la question, comme il est indiqué dépend aussi de comment nous sommes arrivés à la
string
valeur. Pour illustrer:La sortie est:
Ajouter un point de plus pour la réponse.
.EqualsTo()
méthode vous donne la fourniture de comparer à l'encontre de la culture et de la casse.Comme un ajout à la déjà de bonnes réponses: Ce comportement n'est PAS limitée à des Chaînes ou de comparer les différents numbertypes. Même si les deux éléments sont de type objet du même type sous-jacent. "==" ne fonctionne pas.
La capture d'écran suivante montre les résultats de la comparaison de deux objets {int} - valeurs
La
==
jeton en C# est utilisé pour les deux sexes-vérifier les opérateurs. Lorsque le compilateur rencontre le jeton, il va vérifier si l'un des types de rapport a mis en œuvre une égalité-opérateur de surcharge pour la combinaison de types de rapport(*), ou pour une combinaison de types de laquelle les deux types peuvent être converties. Si le compilateur détecte une surcharge, il va l'utiliser. Sinon, si les deux types sont les deux types de référence et ils ne sont pas sans rapport avec les classes (ce pourrait être une interface, ou ils peuvent être liées à des classes), le compilateur va égard==
comme une référence-opérateur de comparaison. Si aucune condition s'applique, la compilation échoue.Noter que certaines autres langues utiliser des jetons pour les deux sexes-vérifier les opérateurs. Dans VB.NET par exemple, le
=
jeton est utilisé dans des expressions uniquement pour la overloadable l'égalité-vérifier l'opérateur, etIs
est utilisé comme référence de test ou null-opérateur de test. Une utilisation=
sur un type qui ne remplace pas l'égalité-vérifier l'opérateur va échouer, tout comme la tentative d'utilisation deIs
pour des fins autres que les tests de référence de l'égalité ou de nullité.(*)Types généralement que la surcharge de l'égalité pour la comparaison avec eux-mêmes, mais il peut être utile pour les types de la surcharge de l'opérateur d'égalité, à des fins de comparaison avec d'autres types particuliers; par exemple,
int
pourrait avoir (et à mon avis doit avoir, mais ne l'a pas) a défini l'un des opérateurs d'égalité pour la comparaison avecfloat
, de sorte que 16777217 ne serait pas le rapport lui-même égal à 16777216f. Comme il est, depuis pas un tel opérateur est défini, C# sera de promouvoir l'int
àfloat
, arrondi à 16777216f avant l'égalité-vérifier l'opérateur voit, que l'opérateur voit alors deux nombres à virgule flottante et les rapports d'égal à égal, dans l'ignorance de l'arrondissement qui ont eu lieu.3
comme étant égal à3.0f
. Si nous avons besoin de la programmeur-à-dire à ce qui est prévu dans tous les cas, il n'y a pas de danger de comportement par défaut conduisant à des résultats inattendus, car il n'est pas le comportement par défaut.Vraiment excellentes réponses et des exemples!
Je voudrais seulement ajouter de la différence fondamentale entre les deux,
Avec ce concept à l'esprit, si vous le travail de tout exemple (en regardant la main gauche et la main droite type de référence, et la vérification de/savoir si le type a en fait == opérateur surchargé et est Égal d'être surchargée), vous êtes certain d'obtenir la bonne réponse.
Lorsque nous créer n'importe quel objet il y a deux parties de l'objet est le contenu et l'autre est en référence à ce contenu.
==
compare à la fois de contenu et de référence;equals()
compare uniquement le contenuhttp://www.codeproject.com/Articles/584128/What-is-the-difference-between-equalsequals-and-Eq
a
etb
sont à la fois de la chaîne de références, alors le résultat dea == b
ne dépend pas de savoir si les références pointent vers le même objet.==
L'opérateur == peut être utilisé pour comparer deux variables de tout type, et il compare simplement les bits.
Remarque : il y a plus de zéros sur le côté gauche de l'int, mais nous ne se soucient pas ce sujet ici.
int a (00000011) == byte b (00000011)
Souviens opérateur == ne se préoccupe que de la répétition des bits de la variable.
Utiliser == Si deux références (primitives), se réfère au même objet sur le tas.
Règles sont les mêmes si la variable est une référence ou primitif.
a == c est vrai
a == b est faux
le motif de bits sont les mêmes pour a et c, de sorte qu'ils sont égaux à l'aide de ==.
L'égalité():
Utiliser la méthode equals() pour voir si deux objets sont égaux.
Comme deux objets String qui représentent tous deux des personnages de "Jane"
object a = 3; object b = 3; Console.WriteLine(a == b);
. La sortie est faux, même si les motifs de bits des valeurs sont les mêmes. Les types des opérandes sont également importants. La raison pour laquelle nous "don't care" sur le nombre de zéros dans votre exemple, que par l'appel de l'opérateur=, le nombre de zéros est en fait, le même, en raison de la conversion implicite.La seule différence entre l'Égalité et l' == est le type d'objet de comparaison. dans d'autres cas, tels que les types de référence et des types de valeur, ils sont presque les mêmes(soit les deux sont au niveau des bits de l'égalité, ou les deux, sont pour la référence à l'égalité).
objet:
Est égal à: bit-wise de l'égalité
==: référence de l'égalité
chaîne: (d'égal à égal et == sont les mêmes pour la chaîne, mais si l'un de chaîne a changé d'objet, puis le résultat de la comparaison sera différent)
Est égal à: bit-wise de l'égalité
== : bit-wise égalité
Voir ici pour plus d'explication.