studio - tipos de librerias en c#
¿Cuál es la diferencia entre== e Igual() para las primitivas en C#? (9)
Respuesta corta:
La igualdad es complicada.
Respuesta detallada:
Los tipos primitivos anulan el object.Equals(object)
base. object.Equals(object)
y devuelven verdadero si el object
caja es del mismo tipo y valor. (Tenga en cuenta que también funcionará para tipos anulables; los tipos nulos que no aceptan nulos siempre se ajustan a una instancia del tipo subyacente).
Como newAge
es un short
, su método Equals(object)
solo devuelve true si pasa un short en caja con el mismo valor. Estás pasando un int
encuadrado, por lo que devuelve falso.
Por el contrario, el operador ==
se define como tomar dos int
s (o short
s o long
s).
Cuando lo llames con un int
y un short
, el compilador convertirá implícitamente el short
a int
y comparará los int
resultantes por valor.
Otras formas de hacerlo funcionar
Los tipos primitivos también tienen su propio método Equals()
que acepta el mismo tipo.
Si escribe age.Equals(newAge)
, el compilador seleccionará int.Equals(int)
como la mejor sobrecarga y convertirá implícitamente short
a int
. Luego devolverá true
, ya que este método simplemente compara los int
s directamente.
short
también tiene un short.Equals(short)
, pero int
no se puede convertir implícitamente en short
, por lo que no lo está llamando.
Podría forzarlo a llamar a este método con un molde:
Console.WriteLine(newAge.Equals((short)age)); // true
Esto llamará short.Equals(short)
directamente, sin boxeo. Si la age
es mayor que 32767, arrojará una excepción de desbordamiento.
También puede llamar a la short.Equals(object)
, pero pasar explícitamente un objeto en caja para que tenga el mismo tipo:
Console.WriteLine(newAge.Equals((object)(short)age)); // true
Al igual que la alternativa anterior, esto arrojará un desbordamiento si no cabe en un short
. A diferencia de la solución anterior, encajonará el short
en un objeto, perdiendo tiempo y memoria.
Código fuente:
Aquí hay ambos métodos Equals()
del código fuente actual:
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;
}
Otras lecturas:
Considera este código:
int age = 25;
short newAge = 25;
Console.WriteLine(age == newAge); //true
Console.WriteLine(newAge.Equals(age)); //false
Console.ReadLine();
Tanto int
como short
son tipos primitivos, pero una comparación con ==
devuelve true y una comparación con Equals
devuelve false.
¿Por qué?
Cuando pasa int
a short
''s Iguala pasa object
:
Entonces este pseudocódigo corre:
return obj is short && this == (short)obj;
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ícito. Si el compilador puede hacer que todos los argumentos satisfagan a sus operadores y métodos agregando conversiones implícitas, lo hará sin queja, aunque en algunos casos (¡especialmente con pruebas de igualdad!) Los resultados pueden ser sorprendentes.
Además, cada tipo de valor, como int
o short
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 en su tipo correspondiente de objeto, pero los diferentes tipos de objetos no son implícitamente convertibles entre sí.
Si uno usa el operador ==
para comparar un short
y un int
, el short
se convertirá implícitamente en un int
. Si su valor numérico fue igual al de int
, el int
al que se convirtió será igual al int
con el que se compara. Sin embargo, si se intenta utilizar el método Equals
en el corto para compararlo con un int
, la única conversión implícita que satisfaría una sobrecarga del método Equals
sería la conversión al tipo de objeto correspondiente a int
. Cuando se le pregunta al short
si coincide con el objeto pasado, observará que el objeto en cuestión es un int
lugar de un short
y, por lo tanto, concluye que posiblemente no sea igual.
En general, aunque el compilador no se quejará de eso, uno debe evitar comparar cosas que no son del mismo tipo; si uno está interesado en si la conversión de cosas a una forma común daría el mismo resultado, uno debería realizar dicha conversión explícitamente. Considera, por ejemplo,
int i = 16777217;
float f = 16777216.0f;
Console.WriteLine("{0}", i==f);
Hay tres formas en que uno puede querer comparar un int
con un float
. Uno puede querer saber:
- ¿El valor
float
más cercano posible alint
coincide con elfloat
? - ¿La parte entera del
float
coincide con elint
? - Los valores
int
yfloat
representan el mismo valor numérico.
Si uno intenta comparar un int
y float
directamente, el código compilado responderá a la primera pregunta; si eso es lo que el programador pretendió, sin embargo, no será nada obvio. Cambiar la comparación a (float)i == f
dejaría en claro que el primer significado fue intencionado, o (double)i == (double)f
haría que el código responda la tercera pregunta (y aclare que eso fue lo que destinado a).
(*) Incluso si la especificación de C # se refiere a un valor de tipo p. Ej. System.Int32
como un objeto de tipo System.Int32
, dicha visión se contradice con el requisito de que un código se ejecute en una plataforma cuya especificación se refiere a valores y objetos que habitan diferentes universos. Además, si T
es un tipo de referencia, x
es un T
, entonces una referencia de tipo T
debería poder referirse a x
. Por lo tanto, si una variable v
de tipo Int32
contiene un Object
, una referencia de tipo Object
debería poder contener una referencia a v
o su contenido. De hecho, una referencia de tipo Object
podría apuntar a un objeto que contiene datos copiados de v
, pero no a v
ni a sí mismo ni a su contenido. Eso sugeriría que ni v
ni su contenido son realmente un Object
.
Lo que necesita darse cuenta es que hacer ==
siempre terminará llamando a un método. La pregunta es si llamar ==
e Equals
termina haciendo llamadas / haciendo las mismas cosas.
Con tipos de referencia, ==
siempre verificará primero si las referencias son las mismas ( Object.ReferenceEquals
). Equals
por otro lado, puede anularse y puede verificar si algunos valores son iguales.
EDITAR: para responder svick y agregar el comentario de SLaks, aquí hay un código 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.
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 los mismos.
Object.Equals
http://msdn.microsoft.com/en-us/library/bsc2ak47(v=vs.110).aspx
Porque no hay sobrecarga para short.Equals
que aceptan un int
. Por lo tanto, esto se llama:
public override bool Equals(object obj)
{
return obj is short && this == (short)obj;
}
obj
no es un short
... por lo tanto, es falso.
==
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 habrá un tipo de conversión hecho e Equals
también se usa para la comprobación es igual a la condición, pero en este caso los tipos de datos deben ser iguales. N Equals es un método, no un operador.
A continuación se muestra un pequeño ejemplo tomado del que usted proporcionó y esto aclarará la diferencia en pocas palabras.
int x=1;
short y=1;
x==y;//true
y.Equals(x);//false
en el ejemplo anterior, X e Y tienen los mismos valores, es decir 1, y cuando usamos ==
, devolverá verdadero, como en el caso de ==
, el compilador convertirá el tipo abreviado en int y se dará el resultado.
y cuando usamos Equals
, la comparación se hace, pero el tipo de conversión no se realiza por el compilador, por lo que se devuelve falso.
Chicos, por favor, háganme saber si estoy equivocado.
== En primitivo
Console.WriteLine(age == newAge); // true
En la comparación primitiva, el operador == se comporta de manera bastante obvia, en C # hay muchas == sobrecarga del operador disponible.
- cadena == cadena
- int == int
- uint == uint
- largo == largo
- mucho mas
Entonces en este caso no hay conversión implícita de int
a short
pero short
to int
es posible. Entonces, newAge se convierte en int y se produce una comparación que devuelve true ya que ambos tienen el mismo valor. Entonces es equivalente a:
Console.WriteLine(age == (int)newAge); // true
.Equals () en Primitive
Console.WriteLine(newAge.Equals(age)); //false
Aquí tenemos que ver qué método es Equals (), llamamos a Equals con una variable de tipo abreviada. Entonces hay tres posibilidades:
- Igual (objeto, objeto) // método estático del objeto
- Igual (objeto) // método virtual del objeto
- Igual (corto) // Implementa EQuables.Equals (corto)
El primer tipo no es el caso aquí ya que el número de argumentos es diferente que llamamos con solo un argumento de tipo int. En tercer lugar también se elimina como se mencionó anteriormente la conversión implícita de int a corto no es posible. Entonces aquí se llama el segundo tipo de Equals(object)
. El short.Equals(object)
es:
bool Equals(object z)
{
return z is short && (short)z == this;
}
Así que aquí la condición se puso a prueba z is short
que es falsa, ya que z es una int, por lo que devuelve false.
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 que los valores son los mismos.
Por favor, no te confundas con ReferenceEqual
Referencia igual ()
Sintaxis: bool estático público ReferenceEquals ()
Determina si la instancia de los objetos especificados es de la misma instancia