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
o short
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 ay short
an int
, el short
se convertirá implícitamente en an int
. Si su valor numérico es igual al del int
, el int
al que se convirtió será igual int
al que se compara. Sin embargo, si se intenta utilizar el Equals
método en corto para compararlo con un int
, la única conversión implícita que satisfaría una sobrecarga del Equals
método sería la conversión al tipo de objeto correspondiente int
. Cuando short
se le pregunta si coincide con el objeto pasado, observará que el objeto en cuestión es int
más bien que un short
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,
int i = 16777217;
float f = 16777216.0f;
Console.WriteLine("{0}", i==f);
Hay tres formas en que uno podría comparar una int
a una float
. Uno podría querer saber:
- ¿Coincide el
float
valor más cercano posible con int
el float
?
- ¿La parte del número entero
float
coincide con el int
?
- Haz
int
y float
representa el mismo valor numérico.
Si uno intenta comparar int
y float
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 tipo System.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, si T
es un tipo de referencia, y x
es un T
, entonces una referencia de tipo T
debería poder referirse x
. Por lo tanto, si una variable v
de tipo Int32
contiene una 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 v
, pero no a v
sí mismo ni a su contenido. Eso sugeriría que ningunov
ni su contenido es realmente un Object
.