Quelle est la différence entre == et Equals() pour les primitives en C#?
Considérer ce code:
int age = 25;
short newAge = 25;
Console.WriteLine(age == newAge); //true
Console.WriteLine(newAge.Equals(age)); //false
Console.ReadLine();
Les deux int
et short
sont les types primitifs, mais une comparaison avec ==
retourne true et une comparaison avec Equals
renvoie la valeur false.
Pourquoi?
- Veuillez Réfléchir à la question et ensuite voter pour fermer
- C'est le manque évident inverse tentative:
Console.WriteLine(age.Equals(newAge));
- Les deux questions peuvent être répondues par la même explication de la façon dont les deux syntaxes diffèrent dans la sémantique. Si vous vous sentez d'ailleurs, les titres des questions qui doit être changé.
- Le double ne permet pas d'expliquer ce comportement; c'est à peu près ce que
Equals()
est en général. - cette question n'est pas en double
- J'ai répondu à cette question exacte sur le Coverity blog il y a quelques jours. blog.coverity.com/2014/01/13/inconsistent-equality
- Ce qui se passe avec
age.Equals(newAge);
? - Il n'y a pas de notion de "types primitifs" en C#, et même si elle existait, il serait hors de propos. C'est à propos de la surcharge de
==
et dominanteEquals
pour obtenir la valeur de référence de la sémantique. - Je ne suis pas sûr de savoir comment connexes, c'est à cette question, mais
double.NaN
n'est pas==
-égal à lui-même, mais il neEquals
lui-même. - ReSharper dit: Suspicion de comparaison: il n'y a pas de type dans la solution qui est hérité des deux "court" et "int"
- La spécification utilise le terme de "types primitifs" à deux reprises, sans jamais la définir; la conséquence en est que les types primitifs sont intégrés dans les types de valeur, mais ce n'est jamais clair. Je l'ai recommandé à Mads que le terme simplement être rayé de la spécification comme il semble créer plus de confusion qu'il supprime.
- Voir: stackoverflow.com/a/2111905
- Savez-vous à propos de C#?
- Qu'est-ce que liées entre boxing et unboxing et cette question?
- C# à la différence de Java, n'ont pas réellement de Primitives. Les numéros etc sont le type de Référence (pour utiliser java termes). La plupart des choses que Java serait appelé Primitives sont en C#, juste des types qui implémentent
IConvertible, IComparable<T>, IEquatable<T>
je pense que la chose importante ici est laIEquatable<T>
interface (et les règles et les conventions autour d'elle.) - Complètement faux. Les numéros en C# sont des types valeur, et peut être mis en boîte à
object
, qui est à l'origine du problème ici. Cela n'a rien à voir avecIEquatable<T>
. - C# v1033 Spec, Page 1:
C# has a unified type system. All C# types, including primitive types such as int and double, inherit from a single root object type. Thus, all types share a set of common operations, and values of any type can be stored, transported, and *operated upon in a consistent manner.*
Le mot Primitif est mentionné qu'une seule autre fois dans la spec, page 361 (paraphased pour le contexte)"Primitive" [sic] types are implemented as structs
Pour toutes fins utiles, le mot primitif n'a pas de sens dans le langage C#. La question peut effectivement se rapportent àstructs
si - Oui (voir Eric Lippert du commentaire), mais les types de valeur ne sont pas les types de référence (sauf en boîte). Bien que cette question allait encore se faire avec les types de référence trop.
- Désolé je manque interpretted "Complètement faux", Vous avez raison, des chiffres, etc sont des types de Valeur, pas de refernce types (my bad). Parce qu'ils sont des structures. Peut-être que la question devrait être editted-à-dire
value types
au lieu de "primitives". Mon problème est que le primitve mot ne doit pas être utilisé ici. - Ce n'est pas en fait une réplique de l'une de ces questions. Par exemple, ce comportement est complètement indépendant de la boxe.
- Une bonne raison pour laquelle ce est balisé javascript?
Vous devez vous connecter pour publier un commentaire.
Réponse courte:
L'égalité est compliqué.
Réponse détaillée:
Primitives types de remplacer la base de
object.Equals(object)
et retourne true si la boîteobject
est de la même type et de la valeur. (Notez que cela fonctionne également pour les types nullables; non-null types nullables toujours à cocher pour une instance du type sous-jacent.)Depuis
newAge
est unshort
, sonEquals(object)
méthode ne renvoie vrai si vous passez un coffret court avec la même valeur. Vous êtes de passage un coffretint
, elle retourne false.En revanche, la
==
opérateur est défini comme la prise de deuxint
s (oushort
s oulong
s).Lorsque vous appelez avec un
int
et unshort
, le compilateur va convertir implicitement leshort
àint
et de comparer l'résultantint
s par valeur.D'autres moyens de faire fonctionner
Types primitifs ont aussi leur propre
Equals()
méthode qui accepte du même type.Si vous écrivez
age.Equals(newAge)
, le compilateur choisiraint.Equals(int)
comme le meilleur de surcharge et de convertir implicitementshort
àint
. Il sera ensuite de retour àtrue
, puisque cette méthode compare simplement leint
s directement.short
a aussi unshort.Equals(short)
méthode, maisint
ne peut pas être implicitement converti àshort
, de sorte que vous ne sont pas en l'appelant.Vous pourraient le forcer à appeler cette méthode avec un cast:
Cela appel
short.Equals(short)
directement, sans la boxe. Siage
est supérieure à 32767, il va lever une exception de dépassement de capacité.Vous pouvez aussi appeler le
short.Equals(object)
surcharge, mais explicitement passer un coffret de l'objet afin qu'il soit du même type:Comme la dernière alternative, cela permettra de jeter un dépassement de capacité si elle ne rentre pas dans un
short
.Contrairement à la solution précédente, il sera de la boîte de la
short
dans un objet, de perdre du temps et de la mémoire.Code Source:
Ici sont à la fois
Equals()
méthodes du code source:Pour En Savoir Plus:
Voir Eric Lippert.
long == int
,int
implicitement converti àlong
droit?int age = 25;
àconst int age = 25;
, alors le résultat sera le changement. C'est parce que une conversion implicite deint
àshort
n'existe pas dans ce cas. Voir Implicite constant expression des conversions.Equals(object)
remplacer fonctionne avec le même type ou nullable version du même type.Equals()
compare l'Égalité tout en==
compare Identité==
opérateur compare les types de référence par référence. Pour les types de valeur, et pour les types qui surcharge==
, il ne le fait pas.==
compare Identité (ie. référence de l'objet en mémoire) alors que.Equals()
mesures d'Égalité (si un objet peut être considéré comme l'égal d'un autre, qui peuvent être définis par l'utilisateur). Bien sûr, vous pourriez surcharge de la==
de l'opérateur, et d'assurer que le compilateur va traiter des types de valeur un peu différemment (après tout, ces types sont connus à l'avance), mais c'est un bon court chemin pour se rappeler les différences en général.short
àint
pour la-
de l'opérateur, tout comme==
n'.a.Equals((object)b)
ne serait-il pas? Passer dans un court serait plus précis. Oui, c'est encadré par la suite, mais seulement dans le code qui est exécuté dans lesEquals
méthode.int
n'est pas convertible àshort
. Au lieu de cela, il appelleEquals(object)
, implicitement, de la boxe à la callsite. Lire ma réponse plus attentivement.Car il n'y a pas de surcharge pour
short.Equals
qui accepte unint
. Par conséquent, il est appelé:obj
n'est pas unshort
.. par conséquent, il est faux.Lorsque vous passez
int
àshort
s'est Égal à vous passerobject
:Donc, ce pseudo-code fonctionne:
Pour les types de valeur,
.Equals
exige que les deux objets de même type et ont la même valeur, alors que==
juste des tests, si les deux valeurs sont les mêmes.Object.Equals
http://msdn.microsoft.com/en-us/library/bsc2ak47(v=vs. 110).aspx
==
est utilisé pour vérifier une égalité de condition, il peut être considéré comme un opérateur(opérateur booléen), juste pour comparer 2 choses, et ici, le type de données n'est pas grave car il y aurait une conversion de type de fait etEquals
est également utilisé pour la vérification d'égale condition, mais dans ce cas, les types de données doit être la même. N est Égal à est une méthode qui n'est pas un opérateur.Voici un petit exemple tiré de celui que vous avez fourni et cela permettra de clarifier la différence en bref,.
dans l'exemple ci-dessus, X et Y ont les mêmes valeurs c'est à dire 1, et lorsque nous utilisons
==
, il renverra true, comme dans le cas de==
, le type court est converti en int par le compilateur et le résultat est donné.et lorsque nous utilisons
Equals
, la comparaison est faite, mais le type coulée n'est pas fait par le compilateur, donc, false est retourné.Les gars, s'il vous plaît laissez-moi savoir si je me trompe.
Dans de nombreux contextes où une méthode ou l'exploitant d'argument n'est pas du type requis, le compilateur C# tentera de réaliser un implicite de conversion de type. Si le compilateur peut faire tous les arguments de satisfaire leurs opérateurs et les méthodes en ajoutant des conversions implicites, il le fera sans plainte, même si dans certains cas (surtout avec les tests d'égalité!) les résultats peuvent être surprenants.
En outre, chaque type de valeur tels que
int
oushort
décrit en fait à la fois une sorte de valeur et un type d'objet(*). Les conversions implicites existent pour convertir des valeurs à d'autres types de valeurs, et de convertir n'importe quel type de valeur correspondant à son type d'objet, mais les différents types d'objets ne sont pas implicitement convertible uns des autres.Si l'on utilise le
==
opérateur de comparer unshort
et unint
, leshort
sera implicitement converti enint
. Si sa valeur numérique est égale à celle de laint
, leint
à laquelle il a été converti sera égale à laint
auquel il est comparé. Si l'on tente d'utiliser laEquals
méthode sur le court afin de le comparer avec unint
, cependant, la seule conversion implicite qui serait à même de satisfaire une surcharge de laEquals
de la méthode de la conversion vers le type d'objet correspondant àint
. Lorsque leshort
est demandé si elle correspond à l'objet, il observe que l'objet en question est unint
plutôt qu'unshort
et donc en conclure qu'il ne peut pas être égal.En général, bien que le compilateur ne pas s'en plaindre, il faut éviter de comparer des choses qui ne sont pas du même type; si l'on est intéressé de savoir si la conversion de choses à une forme commune donnerait le même résultat, il faut effectuer une telle conversion explicite. Considérons, par exemple,
Il y a trois façons dont on pourrait vouloir comparer un
int
à unfloat
. On peut avoir envie de savoir:float
de la valeur à laint
correspondre à lafloat
?float
correspondre à laint
?int
etfloat
représentent la même valeur numérique.Si l'on essaie de comparer un
int
etfloat
directement, le code compilé de répondre à la première question; si c'est ce que le programmeur a prévu, cependant, sera loin d'être évidente. La modification de la comparaison de(float)i == f
, il serait clair que le sens premier était destiné, ou(double)i == (double)f
serait la cause de la code de répondre à la troisième question (et il est clair que de ce qui était prévu).( * ), Même si le C# spec ce qui concerne une valeur de type par exemple
System.Int32
comme étant un objet de typeSystem.Int32
, un tel point de vue est contredit par l'exigence d'un code exécuté sur une plate-forme dont les spec ce qui concerne les valeurs et les objets peuplant les différents univers. De plus, siT
est un type de référence, etx
est unT
, une référence de typeT
devrait être en mesure de se référer àx
. Ainsi, si une variablev
de typeInt32
est titulaire d'unObject
, une référence de typeObject
devrait être en mesure de maintenir une référence àv
ou de son contenu. En fait, une référence de typeObject
serait en mesure de pointer un objet contenant les données copiées à partir dev
, mais de ne pasv
elle-même, ni de son contenu. Qui laisserait à penser que niv
ni son contenu est vraiment unObject
.the only implicit conversion which would satisfy an overload of the Equals method would be the conversion to the object type corresponding to int
Mal. Contrairement à Java, C# il n'y a pas de primitive et encadré types. C'est être enfermé dans une boîte àobject
parce que c'est la seule autre surcharge deEquals()
.float
. Le moulage d'unfloat
à undouble
sera pas la baguette magique pour créer de nouveaux précision.List<String>.Enumerator
et un tas d'objet de typeList<String>.Enumerator
sont les mêmes, mais l'ECMA/CLI spec dit qu'ils sont différents, et même lorsqu'il est utilisé en C# ils se comportent différemment.i
etf
chacune ont été convertis àdouble
avant la comparaison, elles donneront 16777217.0 et 16777216.0, qui comparent les plus inégaux. La conversion dei
float
donnerait 16777216.0 f, en comparant égal àf
.bool SelfSame<T>(T p) { return Object.ReferenceEquals((Object)p,(Object)p);}
. La boîte contenant le type d'objet correspondant à un type de valeur peut satisfaire le type de paramètre deReferenceEquals
via un la préservation de l'identité sortie; l'emplacement de stockage type, cependant, nécessite un non-identité-la préservation de conversion. Si l'incantation d'unT
àU
donne une référence à quelque chose d'autre que l'originalT
, qui donnerait à penser qu'unT
n'est pas vraiment unU
.T
? AFAIR C++/CLI qui a la syntaxe pour représenter les "boxed " int" avecint^
utiliseValueType
ouObject
pour ceux qui ont une certaine coutume de marquage qui serait un peu bizarre si vous pouvez réellement utiliser ces.System.Int32
est utilisé pour décrire un emplacement de stockage, il identifie l'emplacement de stockage de type. Lorsqu'il est utilisé pour décrire un objet tas, il identifie le tas type d'objet. Le CLR ne fournit aucun moyen de définir une référence de type emplacement de stockage qui est contraint de tenir uniquement les références à des tas d'objets de typeInt32
.Equals() est une méthode de Système.Objet Classe
Syntaxe : Public virtual bool Equals()
Recommandation si l'on veut comparer l'état de deux objets alors nous devons utiliser Equals() méthode
comme indiqué ci-dessus réponses == opérateurs de comparer les valeurs sont les mêmes.
S'il vous plaît ne pas se confondre avec ReferenceEqual
De Référence Est Égal À()
Syntaxe : public static bool ReferenceEquals()
Il déterminer si les objets de l'instance sont de la même instance
Ce que vous devez comprendre est que faire
==
finis toujours par l'appel d'une méthode. La question est de savoir si l'appelant==
etEquals
finit par appel/de faire les mêmes choses.Avec les types référence,
==
sera toujours 1er vérifier si les références sont les mêmes (Object.ReferenceEquals
).Equals
sur l'autre main peut être remplacée et peut vérifier si certaines valeurs sont égales.EDIT: pour répondre à svick et ajouter sur SLaks commentaire, voici un peu de code IL
int
s avec == appel? Indice: il n'y a pas deoperator ==
méthode pourInt32
, mais il y en a pourString
.==
n'est pas seulement faire de la magie, il a finalement fait simplement appel à une méthode (la plupart des programmeurs probablement jamais mis en œuvre/substituée tout opérateur). Peut-être que je pourrais avoir ajouté un commentaire à votre question au lieu d'y ajouter ma propre réponse. Se sentir libre de mettre à jour le vôtre si vous vous sentez ce que j'ai dit est pertinent.==
sur les types primitifs n'est pas un opérateur surchargé, mais d'une caractéristique intrinsèque de la langue fonctionnalité qui compile à laceq
instruction IL.== Primitive De
Primitive de comparaison ==, opérateur se comportent tout à fait évident, En C# il y a beaucoup opérateur == surcharge disponible.
Donc dans ce cas il n'y a pas de conversion implicite de
int
àshort
maisshort
àint
est possible. Donc, newAge est converti en int et de comparaison qui renvoie la valeur true à la fois comme titulaire d'une même valeur. Donc c'est équivalent à:.Equals() de Primitives
Ici, nous avons besoin de voir quelle méthode Equals() est, nous appelant égal à Égal avec une courte type de variable. Il y a donc trois possibilités:
Premier type n'est pas le cas ici, que le nombre d'arguments, qui sont différents de nous appeler avec un seul argument de type int. La troisième est également éliminée comme mentionné ci-dessus de la conversion implicite de type int à court n'est pas possible. Voici donc le Deuxième type de
Equals(object)
est appelé. Leshort.Equals(object)
est:Voici donc la condition ai testé
z is short
qui est faux, comme z est un int donc elle retourne false.Ici est détaillée à l'article d'Eric Lippert