Considera este código:
int age = 25;
short newAge = 25;
Console.WriteLine(age == newAge); //true
Console.WriteLine(newAge.Equals(age)); //false
Console.ReadLine();
Ambos int
y short
son tipos primitivos, pero una comparación con ==
devuelve verdadero y una comparación con Equals
devuelve falso.
¿Por qué?
Console.WriteLine(age.Equals(newAge));
Equals()
es en general.Respuestas:
Respuesta corta:
La igualdad es complicada.
Respuesta detallada:
Los tipos primitivos anulan la base
object.Equals(object)
y devuelven verdadero si el recuadroobject
es del mismo tipo y valor. (Tenga en cuenta que también funcionará para los tipos anulables; los tipos anulables no nulos siempre encajonan en una instancia del tipo subyacente).Como
newAge
es ashort
, suEquals(object)
método solo devuelve verdadero si pasa un short en caja con el mismo valor. Estás pasando un cuadroint
, por lo que devuelve falso.Por el contrario, el
==
operador se define como tomar dosint
s (oshort
solong
s).Cuando se llama con una
int
y unashort
, el compilador convertir implícitamente elshort
queint
y comparar el resultadoint
s por valor.Otras formas de hacerlo funcionar
Los tipos primitivos también tienen su propio
Equals()
método que acepta el mismo tipo.Si escribe
age.Equals(newAge)
, el compilador seleccionaráint.Equals(int)
como la mejor sobrecarga y se convertirá implícitamenteshort
aint
. Luego regresarátrue
, ya que este método simplemente compara laint
s directamente.short
también tiene unshort.Equals(short)
método, peroint
no se puede convertir implícitamenteshort
, por lo que no lo está llamando.Podría forzarlo a llamar a este método con un yeso:
Esto llamará
short.Equals(short)
directamente, sin boxeo. Siage
es mayor que 32767, generará una excepción de desbordamiento.También podría llamar a la
short.Equals(object)
sobrecarga, pero pasar explícitamente un objeto en caja para que obtenga el mismo tipo:Al igual que la alternativa anterior, esto generará un desbordamiento si no cabe en a
short
. A diferencia de la solución anterior, lo encajonaráshort
en un objeto, perdiendo tiempo y memoria.Código fuente:
Estos son los dos
Equals()
métodos del código fuente real:Otras lecturas:
Ver Eric Lippert .
fuente
long == int
, ¿int
convertido implícitamente a lalong
derecha?int age = 25;
aconst int age = 25;
, entonces el resultado cambiará. Esto se debeint
ashort
que en ese caso existe una conversión implícita de a . Ver Conversiones implícitas de expresión constante .==
compara los tipos de referencia por referencia. Para los tipos de valor y para los tipos que se sobrecargan==
, no lo hace.Porque no hay sobrecarga para
short.Equals
eso acepta unint
. Por lo tanto, esto se llama:obj
no es unshort
... por lo tanto, es falso.fuente
Cuando pasas
int
ashort
's Equals, pasasobject
:Entonces este pseudocódigo se ejecuta:
fuente
Para los tipos de valor,
.Equals
requiere que los dos objetos sean del mismo tipo y tengan el mismo valor, mientras que==
solo prueba si los dos valores son iguales.Object.Equals
http://msdn.microsoft.com/en-us/library/bsc2ak47(v=vs.110).aspx
fuente
==
se usa para verificar una condición igual, se puede considerar como un operador (operador booleano), solo para comparar 2 cosas y aquí el tipo de datos no importa, ya que se realizaría una conversión de tipo yEquals
también se usa para verificar condiciones iguales , pero en este caso los tipos de datos deberían ser los mismos. N Equals es un método, no un operador.A continuación se muestra un pequeño ejemplo tomado del que proporcionó y esto aclarará brevemente la diferencia.
en el ejemplo anterior, X e Y tienen los mismos valores, es decir, 1, y cuando usamos
==
, devolverá verdadero, ya que en el caso de==
, el compilador convierte el tipo corto en int y se da el resultado.y cuando usamos
Equals
, se realiza la comparación, pero el compilador no realiza la conversión de tipos, por lo que se devuelve falso.Chicos, por favor avíseme si me equivoco.
fuente
En muchos contextos donde un método o argumento de operador no es del tipo requerido, el compilador de C # intentará realizar una conversión de tipo implícita. Si el compilador puede hacer que todos los argumentos satisfagan sus operadores y métodos agregando conversiones implícitas, lo hará sin quejarse, aunque en algunos casos (¡especialmente con pruebas de igualdad!) Los resultados pueden ser sorprendentes.
Además, cada tipo de valor tal como
int
oshort
realmente describe tanto un tipo de valor como un tipo de objeto (*). Existen conversiones implícitas para convertir valores a otros tipos de valores y para convertir cualquier tipo de valor a su tipo de objeto correspondiente, pero los diferentes tipos de objetos no son implícitamente convertibles entre sí.Si uno usa el
==
operador para comparar ayshort
anint
, elshort
se convertirá implícitamente en anint
. Si su valor numérico es igual al delint
, elint
al que se convirtió será igualint
al que se compara. Sin embargo, si se intenta utilizar elEquals
método en corto para compararlo con unint
, la única conversión implícita que satisfaría una sobrecarga delEquals
método sería la conversión al tipo de objeto correspondienteint
. Cuandoshort
se le pregunta si coincide con el objeto pasado, observará que el objeto en cuestión esint
más bien que unshort
y, por lo tanto, concluirá que no puede ser igual.En general, aunque el compilador no se quejará, se debe evitar comparar cosas que no son del mismo tipo; Si uno está interesado en saber si la conversión de cosas a una forma común daría el mismo resultado, debería realizar dicha conversión explícitamente. Considere, por ejemplo,
Hay tres formas en que uno podría comparar una
int
a unafloat
. Uno podría querer saber:float
valor más cercano posible conint
elfloat
?float
coincide con elint
?int
yfloat
representa el mismo valor numérico.Si uno intenta comparar
int
yfloat
directamente, el código compilado responderá la primera pregunta; si eso es lo que pretendía el programador, sin embargo, estará lejos de ser obvio. Cambiar la comparación a(float)i == f
dejaría en claro que se pretendía el primer significado, o(double)i == (double)f
haría que el código respondiera a la tercera pregunta (y dejaría claro que eso era lo que se pretendía).(*) Incluso si la especificación de C # considera un valor de tipo, por ejemplo,
System.Int32
como un objeto de tipoSystem.Int32
, tal opinión se contradice con el requisito de que un código se ejecute en una plataforma cuya especificación considere valores y objetos que habitan universos diferentes. Además, siT
es un tipo de referencia, yx
es unT
, entonces una referencia de tipoT
debería poder referirsex
. Por lo tanto, si una variablev
de tipoInt32
contiene unaObject
, una referencia de tipoObject
debería poder contener una referencia av
o su contenido. De hecho, una referencia de tipoObject
podría apuntar a un objeto que contiene datos copiadosv
, pero no av
sí mismo ni a su contenido. Eso sugeriría que ningunov
ni su contenido es realmente unObject
.fuente
the only implicit conversion which would satisfy an overload of the Equals method would be the conversion to the object type corresponding to int
Incorrecto. A diferencia de Java, C # no tiene tipos primitivos y en caja separados. Está en cajaobject
porque esa es la única otra sobrecarga deEquals()
.float
. Lanzar unfloat
a adouble
no creará mágicamente una nueva precisión.List<String>.Enumerator
y un objeto de almacenamiento dinámico de tipoList<String>.Enumerator
son los mismos, pero la especificación de ECMA / CLI dice que son diferentes, e incluso cuando se usan en C # se comportan de manera diferente.i
yf
fueron cada convertido adouble
antes de la comparación, se producirían 16777217.0 y 16777216.0, que compara como desigual. La conversióni
float
produciría 16777216.0f, comparando igual af
.bool SelfSame<T>(T p) { return Object.ReferenceEquals((Object)p,(Object)p);}
. El tipo de objeto en recuadro correspondiente a un tipo de valor puede satisfacer el tipo de parámetro aReferenceEquals
través de una transmisión de preservación de identidad ; sin embargo, el tipo de ubicación de almacenamiento requiere una conversión que no preserva la identidad . Si emitir unT
aU
produce una referencia a algo diferente al originalT
, eso me sugeriría que aT
no es realmente unU
.Equals () es un método de System.Object Class
Sintaxis: Public virtual bool Equals ()
Recomendación si queremos comparar el estado de dos objetos, entonces deberíamos usar el método Equals ()
como se indicó anteriormente, las respuestas == operadores comparan los valores son los mismos.
No te confundas con ReferenceEqual
Reference Equals ()
Sintaxis: public static bool ReferenceEquals ()
Determina si la instancia de objetos especificada es de la misma instancia
fuente
Lo que debe darse cuenta es que hacer
==
siempre terminará llamando a un método. La pregunta es si llama==
yEquals
termina llamando / haciendo las mismas cosas.Con los tipos de referencia,
==
siempre verificará primero si las referencias son las mismas (Object.ReferenceEquals
).Equals
por otro lado, puede anularse y verificar si algunos valores son iguales.EDITAR: para responder svick y agregar un comentario de SLaks, aquí hay un código IL
fuente
int
s con == llamada? Sugerencia: no hay unoperator ==
método paraInt32
, pero hay uno paraString
.==
no solo hace magia, sino que finalmente simplemente llama a un método (la mayoría de los programadores probablemente nunca implementaron / anularon ningún operador). Tal vez podría haber agregado un comentario a su pregunta en lugar de agregar mi propia respuesta. Siéntase libre de actualizar la suya si siente que lo que dije es relevante.==
en cuenta que en los tipos primitivos no es un operador sobrecargado, sino una función de lenguaje intrínseca que se compila con laceq
instrucción IL.== en primitivo
En comparación primitiva, el operador == se comporta de manera bastante obvia, en C # hay muchas sobrecargas de operador == disponibles.
Por lo tanto, en este caso no hay conversión implícita de
int
ashort
peroshort
aint
es posible. Entonces newAge se convierte en int y se produce una comparación que devuelve verdadero ya que ambos tienen el mismo valor. Entonces es equivalente a:.Equals () en primitivo
Aquí necesitamos ver qué es el método Equals (), llamamos a Equals con una variable de tipo corto. Entonces hay tres posibilidades:
El primer tipo no es el caso aquí ya que el número de argumentos es diferente al que llamamos con un solo argumento de tipo int. El tercero también se elimina como se mencionó anteriormente, no es posible la conversión implícita de int a short. Así que aquí
Equals(object)
se llama el segundo tipo de . Elshort.Equals(object)
es:Entonces, aquí se probó la condición
z is short
que es falsa ya que z es un int, por lo que devuelve falsoAquí hay un artículo detallado de Eric Lippert
fuente