Considérez 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 des types primitifs, mais une comparaison avec ==
renvoie true et une comparaison avec Equals
renvoie false.
Pourquoi?
Console.WriteLine(age.Equals(newAge));
Equals()
est en général.Réponses:
Réponse courte:
L'égalité est compliquée.
Réponse détaillée:
Les types primitifs remplacent la base
object.Equals(object)
et renvoient true si le boxedobject
est du même type et de la même valeur. (Notez que cela fonctionnera également pour les types Nullable; les types Nullable non Null encadrent toujours une instance du type sous-jacent.)Puisque
newAge
est ashort
, saEquals(object)
méthode ne renvoie vrai que si vous passez un short boxed avec la même valeur. Vous passez une boîteint
, donc il retourne faux.En revanche, l'
==
opérateur est défini comme prenant deuxint
s (oushort
s oulong
s).Lorsque vous l'appelez avec un
int
et unshort
, le compilateur convertira implicitement leshort
toint
et comparera leint
s résultant par valeur.Autres moyens de le faire fonctionner
Les types primitifs ont également leur propre
Equals()
méthode qui accepte le même type.Si vous écrivez
age.Equals(newAge)
, le compilateur sélectionneraint.Equals(int)
la meilleure surcharge et la convertira implicitementshort
enint
. Il reviendra alorstrue
, puisque cette méthode compare simplement lesint
s directement.short
a également uneshort.Equals(short)
méthode, maisint
ne peut pas être convertie implicitement enshort
, donc vous ne l'appelez pas.Vous pouvez le forcer à appeler cette méthode avec un cast:
Cela appellera
short.Equals(short)
directement, sans boxe. Siage
est supérieur à 32767, il lèvera une exception de dépassement de capacité.Vous pouvez également appeler la
short.Equals(object)
surcharge, mais passer explicitement un objet encadré afin qu'il obtienne le même type:Comme l'alternative précédente, cela provoquera un débordement s'il ne rentre pas dans un fichier
short
. Contrairement à la solution précédente, il enfermera leshort
dans un objet, perdant du temps et de la mémoire.Code source:
Voici les deux
Equals()
méthodes du code source réel:Lectures complémentaires:
Voir Eric Lippert .
la source
long == int
,int
implicitement converti enlong
droite?int age = 25;
enconst int age = 25;
, le résultat changera. C'est parce qu'une conversion implicite deint
àshort
existe dans ce cas. Voir Conversions d'expressions constantes implicites .==
compare les types de référence par référence. Pour les types valeur et pour les types surchargés==
, ce n'est pas le cas.Parce qu'il n'y a pas de surcharge pour
short.Equals
cela accepte unint
. Par conséquent, cela s'appelle:obj
n'est pas unshort
.. donc, c'est faux.la source
Lorsque vous passez
int
àshort
's Equals, vous passezobject
:Donc, ce pseudocode s'exécute:
la source
Pour les types valeur,
.Equals
exige que les deux objets soient du même type et aient la même valeur, alors==
qu'il teste simplement si les deux valeurs sont identiques.Object.Equals
http://msdn.microsoft.com/en-us/library/bsc2ak47(v=vs.110).aspx
la source
==
est utilisé pour vérifier une condition d'égalité, 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'a pas d'importance car il y aurait un casting de type fait etEquals
est également utilisé pour vérifier la condition d'égalité , mais dans ce cas, les types de données doivent être identiques. N Equals est une méthode et non un opérateur.Voici un petit exemple tiré de celui que vous avez fourni et cela clarifiera 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 l'utilisons
==
, il retournera true, comme dans le cas de==
, le type court est converti en int par le compilateur et le résultat est donné.et quand nous utilisons
Equals
, la comparaison est faite, mais le cast de type n'est pas fait par le compilateur, donc false est retourné.Les gars, faites-moi savoir si je me trompe.
la source
Dans de nombreux contextes où une méthode ou un argument d'opérateur n'est pas du type requis, le compilateur C # tentera d'effectuer une conversion de type implicite. Si le compilateur peut faire en sorte que tous les arguments satisfassent leurs opérateurs et méthodes en ajoutant des conversions implicites, il le fera sans se plaindre, même si dans certains cas (surtout avec des tests d'égalité!) Les résultats peuvent être surprenants.
En outre, chaque type de valeur tel que
int
oushort
décrit en fait à la fois un type de valeur et un type d'objet (*). Des conversions implicites existent pour convertir des valeurs en d'autres types de valeurs et pour convertir tout type de valeur en son type d'objet correspondant, mais les différents types d'objets ne sont pas implicitement convertibles les uns aux autres.Si l'on utilise l'
==
opérateur pour comparer ashort
et anint
, leshort
sera implicitement converti en unint
. Si sa valeur numérique était égale à celle duint
, leint
auquel il a été converti sera égalint
au auquel il est comparé. Si l'on tente d'utiliser laEquals
méthode sur le short pour la comparer à unint
, cependant, la seule conversion implicite qui satisferait une surcharge de laEquals
méthode serait la conversion vers le type d'objet correspondant àint
. Lorsqu'onshort
lui demande s'il correspond à l'objet passé, il observera que l'objet en question est unint
plutôt qu'un ashort
et conclura ainsi qu'il ne peut pas être égal.En général, même si le compilateur ne s'en plaindra pas, il faut éviter de comparer des choses qui ne sont pas du même type; si l'on veut savoir si la conversion des choses en une forme commune donnerait le même résultat, on devrait effectuer une telle conversion explicitement. Considérez, par exemple,
Il existe trois manières de comparer un
int
à unfloat
. On pourrait vouloir savoir:float
valeur la plus proche possible duint
correspond-elle à lafloat
?float
correspond auint
?int
etfloat
représentez la même valeur numérique.Si l'on essaie de comparer un
int
etfloat
directement, le code compilé répondra à la première question; si c'est ce que le programmeur a voulu, cependant, sera loin d'être évident. Changer la comparaison en(float)i == f
indiquerait clairement que le premier sens était voulu, ou(double)i == (double)f
amènerait le code à répondre à la troisième question (et indiquerait clairement que c'est ce qui était prévu).(*) Même si la spécification C # considère une valeur de type par exemple
System.Int32
comme étant un objet de typeSystem.Int32
, une telle vue est contredite par l'exigence qu'un code s'exécute sur une plate-forme dont la spécification considère les valeurs et les objets comme habitant des univers différents. De plus, siT
est un type de référence, etx
est aT
, alors une référence de typeT
devrait pouvoir faire référencex
. Ainsi, si une variablev
de typeInt32
contient anObject
, une référence de typeObject
doit pouvoir contenir une référence àv
ou à son contenu. En fait, une référence de typeObject
pourrait pointer vers un objet contenant des données copiéesv
, mais pas versv
lui-même ni vers son contenu. Cela suggérerait que niv
ni son contenu n'est vraiment unObject
.la source
the only implicit conversion which would satisfy an overload of the Equals method would be the conversion to the object type corresponding to int
Faux. Contrairement à Java, C # n'a pas de types primitifs et encadrés séparés. Il est encadréobject
parce que c'est la seule autre surcharge deEquals()
.float
. Lancer unfloat
en undouble
ne créera pas comme par magie une nouvelle précision.List<String>.Enumerator
et d'un objet de tas de typeList<String>.Enumerator
sont identiques, mais la spécification ECMA / CLI indique qu'ils sont différents, et même lorsqu'ils sont utilisés en C #, ils se comportent différemment.i
etf
étaient chacun convertisdouble
avant la comparaison, ils donneraient 16777217.0 et 16777216.0, qui se comparent comme inégaux. La conversioni
float
donnerait 16777216.0f, comparant égal àf
.bool SelfSame<T>(T p) { return Object.ReferenceEquals((Object)p,(Object)p);}
. Le type d'objet encadré correspondant à un type valeur peut satisfaire le type de paramètreReferenceEquals
via une conversion ascendante préservant l'identité ; le type d'emplacement de stockage, cependant, nécessite une conversion sans préservation d'identité . Si lancer unT
toU
renvoie une référence à autre chose que l'originalT
, cela me suggère que aT
n'est pas vraiment unU
.Equals () est une méthode de System.Object Class
Syntaxe: Public virtual bool Equals ()
Recommandation si nous voulons comparer l'état de deux objets, nous devrions utiliser la méthode Equals ()
comme indiqué ci-dessus, les réponses == opérateurs comparent les valeurs sont les mêmes.
Veuillez ne pas vous confondre avec ReferenceEqual
Reference Equals ()
Syntaxe: public static bool ReferenceEquals ()
Détermine si l'instance des objets spécifiés est de la même instance
la source
Ce que vous devez réaliser, c'est que faire
==
finira toujours par appeler une méthode. La question est de savoir si appeler==
etEquals
finit par appeler / faire les mêmes choses.Avec les types de référence,
==
vérifiera toujours d'abord si les références sont identiques (Object.ReferenceEquals
).Equals
d'autre part, peut être remplacé et peut vérifier si certaines valeurs sont égales.EDIT: pour répondre à svick et ajouter le commentaire SLaks, voici un code IL
la source
int
s avec == appelle-t-elle? Astuce: il n'y a pas deoperator ==
méthode pourInt32
, mais il y en a une pourString
.==
cela ne fait pas que de la magie, cela appelle finalement simplement une méthode (la plupart des programmeurs n'ont probablement jamais implémenté / remplacé aucun opérateur). J'aurais peut-être pu ajouter un commentaire à votre question au lieu d'ajouter ma propre réponse. N'hésitez pas à mettre à jour le vôtre si vous pensez que ce que j'ai dit est pertinent.==
sur les types primitifs, ce n'est pas un opérateur surchargé, mais une fonctionnalité de langage intrinsèque qui se compile à l'ceq
instruction IL.== En primitif
Dans la comparaison primitive, l'opérateur == se comporte de manière assez évidente, en C # il existe de nombreuses surcharges d'opérateur == disponibles.
Donc, dans ce cas, il n'y a pas de conversion implicite de
int
enshort
maisshort
versint
est possible. Ainsi, newAge est converti en int et la comparaison se produit, ce qui renvoie true car les deux ont la même valeur. Donc c'est équivalent à:.Equals () en primitif
Ici, nous devons voir ce qu'est la méthode Equals (), nous appelons Equals avec une variable de type court. Il y a donc trois possibilités:
Le premier type n'est pas le cas ici car le nombre d'arguments est différent que nous appelons avec un seul argument de type int. Third est également éliminé comme mentionné ci-dessus, la conversion implicite de int en short n'est pas possible. Donc ici le deuxième type de
Equals(object)
est appelé. Leshort.Equals(object)
est:Donc, ici, la condition a été testée,
z is short
ce qui est faux car z est un int donc il retourne faux.Voici l'article détaillé d'Eric Lippert
la source