Considérons ce code:
int age = 25;
short newAge = 25;
Console.WriteLine(age == newAge); //true
Console.WriteLine(newAge.Equals(age)); //false
Console.ReadLine();
int
et short
sont des types primitifs, mais une comparaison avec ==
renvoie true et une comparaison avec Equals
renvoie false.
Pourquoi?
L'égalité est compliquée.
Les types de primitives remplacent la base object.Equals(object)
et retournent la valeur true si la boîte object
est de même type et de valeur. (Notez que cela fonctionnera également pour les types nullable; les types nullable non null sont toujours associés à une instance du type sous-jacent.)
Puisque newAge
est un short
, sa méthode Equals(object)
ne renvoie true que si vous passez un court-circuit court avec la même valeur. Vous passez une boîte int
dans une boîte, donc elle renvoie false.
En revanche, l'opérateur ==
Est défini comme prenant deux int
s (ou short
s ou long
s).
Lorsque vous l'appelez avec un int
et un short
, le compilateur convertira implicitement le short
en int
et comparera le résultat int
s en valeur.
Les types primitifs ont également leur propre méthode Equals()
qui accepte le même type.
Si vous écrivez age.Equals(newAge)
, le compilateur sélectionnera int.Equals(int)
comme meilleure surcharge et convertira implicitement short
en int
. Il retournera ensuite true
, puisque cette méthode compare simplement les int
s directement.
short
a également une méthode short.Equals(short)
, mais int
ne peut pas être converti implicitement en short
, vous ne l'appelez donc pas.
Vous pouvez le forcer à appeler cette méthode avec un casting:
Console.WriteLine(newAge.Equals((short)age)); // true
Ceci appellera short.Equals(short)
directement, sans boxe. Si age
est supérieur à 32767, une exception de dépassement de capacité sera générée.
Vous pouvez également appeler la surcharge short.Equals(object)
, mais explicitement passer un objet encadré afin qu'il ait le même type:
Console.WriteLine(newAge.Equals((object)(short)age)); // true
Comme l’alternative précédente, cela provoquera un débordement s’il ne rentre pas dans un short
. Contrairement à la solution précédente, il encapsulera le short
dans un objet, ce qui entraînera une perte de temps et de mémoire.
Voici les deux méthodes Equals()
du code source actuel:
public override bool Equals(Object obj) {
if (!(obj is Int16)) {
return false;
}
return m_value == ((Int16)obj).m_value;
}
public bool Equals(Int16 obj)
{
return m_value == obj;
}
Voir Eric Lippert .
Parce qu'il n'y a pas de surcharge pour short.Equals
qui accepte un int
. Par conséquent, cela s'appelle:
public override bool Equals(object obj)
{
return obj is short && this == (short)obj;
}
obj
n'est pas un short
.. donc, il est faux.
Pour les types de valeur, .Equals
nécessite que les deux objets soient du même type et aient la même valeur, tandis que ==
_ teste simplement si les deux valeurs sont identiques.
Object.Equals
http://msdn.Microsoft.com/en-us/library/bsc2ak47 (v = vs.110) .aspx
Lorsque vous passez int
à short
, vous transmettez object
:
Donc, ce pseudocode s'exécute:
return obj is short && this == (short)obj;
==
est utilisé pour vérifier une condition égale, 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 importe peu car il y aurait un casting de type et Equals
est également utilisé pour vérifier la condition égale, mais dans ce cas, les types de données doivent être identiques. N Equals est une méthode et non un opérateur.
Vous trouverez ci-dessous un petit exemple tiré de celui que vous avez fourni et qui clarifiera brièvement la différence.
int x=1;
short y=1;
x==y;//true
y.Equals(x);//false
dans l'exemple ci-dessus, X et Y ont les mêmes valeurs, à savoir 1, et lorsque nous utilisons ==
, il retournera vrai, 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 effectuée, mais la conversion de type n'est pas effectuée par le compilateur, donc la valeur false est renvoyée.
Les gars, s'il vous plaît laissez-moi savoir si je me trompe.
Dans de nombreux contextes où un argument de méthode ou d'opérateur n'est pas du type requis, le compilateur C # tente d'effectuer une conversion de type implicite. Si le compilateur parvient à ce que tous les arguments satisfassent leurs opérateurs et leurs méthodes en ajoutant des conversions implicites, il le fera sans problème, même si dans certains cas (en particulier avec des tests d'égalité!) Les résultats peuvent être surprenants.
En outre, chaque type de valeur tel que int
ou short
décrit en fait à la fois un type de valeur et un type d’objet (*). Les conversions implicites existent pour convertir des valeurs en d'autres types de valeurs et pour convertir n'importe quel type de valeur en un type d'objet correspondant, mais les différents types d'objets ne sont pas implicitement convertibles l'un pour l'autre.
Si on utilise le ==
_ opérateur pour comparer un short
et un int
, le short
sera converti implicitement en un int
. Si sa valeur numérique était égale à celle du int
, le int
auquel il a été converti sera égal au int
auquel il est comparé. Si on tente d'utiliser la méthode Equals
sur le court métrage pour la comparer avec un int
, la seule conversion implicite qui satisferait une surcharge de la méthode Equals
serait la conversion en type d'objet correspondant à int
. Quand on demande au short
s'il correspond ou non à l'objet transmis, il s'aperçoit que l'objet en question est un int
plutôt qu'un short
et conclut donc qu'il ne peut pas peut-être être égal.
En général, même si le compilateur ne s'en plaint pas, il faut éviter de comparer des choses qui ne sont pas du même type; si l'on veut savoir si la conversion d'objets en une forme commune donnerait le même résultat, on devrait effectuer cette conversion de manière explicite. Considérons, par exemple,
int i = 16777217;
float f = 16777216.0f;
Console.WriteLine("{0}", i==f);
Il existe trois manières de comparer un int
à un float
. On peut vouloir savoir:
float
la plus proche de int
correspond-elle à float
?float
correspond au int
?int
et float
représentent la même valeur numérique.Si on essaie de comparer directement int
et float
, le code compilé répondra à la première question; Que ce soit ce que le programmeur a prévu, cependant, sera loin d'être évident. Changer la comparaison en (float)i == f
préciserait que le premier sens était voulu, ou (double)i == (double)f
_ obligerait le code à répondre à la troisième question (et préciserait que c'était ce que l'on voulait).
(*) Même si la spécification C # concerne une valeur de type par ex. System.Int32
comme objet de type System.Int32
, une telle vue est contredite par l'exigence qu'un code s'exécute sur une plate-forme dont les spécifications considèrent les valeurs et les objets comme habitant des univers différents. De plus, si T
est un type de référence et que x
est un T
, une référence de type T
devrait pouvoir faire référence à x
. Ainsi, si une variable v
de type Int32
détient un Object
, une référence de type Object
devrait pouvoir contenir une référence à v
ou à son contenu. En fait, une référence de type Object
pourrait pointer sur un objet contenant des données copiées à partir de v
, mais pas sur v
ni sur son contenu. Cela suggérerait que ni v
ni son contenu ne soit réellement un Object
.
Equals () est une méthode de System.Object Class
Syntaxe: Public bool virtuel Equals ()
Recommandation si nous voulons comparer l’état de deux objets, nous devons utiliser la méthode Equals ()
comme indiqué ci-dessus, les réponses == les opérateurs comparent les valeurs sont les mêmes.
S'il vous plaît ne vous trompez pas avec ReferenceEqual
Reference Equals ()
Syntaxe: public static bool ReferenceEquals ()
Détermine si l'instance d'objets spécifiés est de la même instance
Ce que vous devez comprendre, c'est que faire ==
finira toujours par appeler une méthode. La question est de savoir si appeler ==
et Equals
finissent par appeler/faire la même chose.
Avec les types de référence, ==
vérifiera toujours si les références sont les mêmes (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 un commentaire SLaks, voici du code IL
int i1 = 0x22; // ldc.i4.s ie pushes an int32 on the stack
int i2 = 0x33; // ldc.i4.s
short s1 = 0x11; // ldc.i4.s (same as for int32)
short s2 = 0x22; // ldc.i4.s
s1 == i1 // ceq
i1 == s1 // ceq
i1 == i2 // ceq
s1 == s2 // ceq
// no difference between int and short for those 4 cases,
// anyway the shorts are pushed as integers.
i1.Equals(i2) // calls System.Int32.Equals
s1.Equals(s2) // calls System.Int16.Equals
i1.Equals(s1) // calls System.Int32.Equals: s1 is considered as an integer
// - again it was pushed as such on the stack)
s1.Equals(i1) // boxes the int32 then calls System.Int16.Equals
// - int16 has 2 Equals methods: one for in16 and one for Object.
// Casting an int32 into an int16 is not safe, so the Object overload
// must be used instead.
== En primitive
Console.WriteLine(age == newAge); // true
Dans la comparaison primitive, l'opérateur == se comporte assez clairement. En C #, il existe de nombreuses surcharges d'opérateur == disponibles.
Donc, dans ce cas, il n’ya pas de conversion implicite de int
en short
mais short
en int
est possible. Donc newAge est converti en int et une comparaison est effectuée, ce qui retourne true car les deux ont la même valeur. Donc, cela équivaut à:
Console.WriteLine(age == (int)newAge); // true
. Equals () dans Primitive
Console.WriteLine(newAge.Equals(age)); //false
Ici, nous devons voir quelle est la méthode Equals (), en appelant Equals avec une variable de type courte. Donc, il y a trois possibilités:
Le premier type n’est pas le cas ici car le nombre d’arguments est différent. Nous appelons avec un seul argument de type int. Troisième est également éliminé comme mentionné ci-dessus, la conversion implicite de int en short n'est pas possible. Donc, ici, le second type de Equals(object)
est appelé. La short.Equals(object)
est:
bool Equals(object z)
{
return z is short && (short)z == this;
}
Donc ici la condition a été testée z is short
Qui est fausse car z est un int, donc elle retourne fausse.