Optimización de Código - Diferencia entre usar Convert y usar cast - C#
Puedes ver el articulo original en mi blog:
http://juank.black-byte.com/c-optimizacion-codigo-diferencia-convert-toint32-cast/
---
Esta es una duda frecuente cuando quieres convertir de un tipo numérico a otro.
En ese caso hay diferencias importantes sobre todo en cuanto a velocidad de procesamiento.
Veamos 2 ejemplos.
1 - CONVERTIR DE TIPO DECIMAL (DECIMAL) A TIPO INT (INT32):
Si utilizas el operador de cast, es decir : (int)
Explicación básica:
El runtime lo que hará es simplemente tomar la parte entera del número descartando completamente la parte decimal.
Explicación más completa:
del tipo decimal es de 16 bytes mientras que el tipo int es de 4
bytes (casi siempre), así que lo que sucede es que el runtime toma la
parte entera del tipo decimal y la coloca en los 4 bytes enteros, pero atención, eso solo siempre y cuando la parte entera del dato tipo decimal quepa en 2^32 , de lo contrario se genera una excepción de overflow.
Si utilizas el Convert.ToInt32
Explicación básica:
Cuando el método estático Convert.ToInt32() (en adelante solo ToInt32)
recibe como parámetro un tipo de dato Decimal hace más que solo
retornar la parte entera, de hecho redondea el resultado al entero más
cercano. Esto genera una sobrecarga adicional que lo hace mucho más
lento.
Explicación más completa:
ToInt32 cuando recibe un tipo Decimal llama al método interno Decimal.FCallToInt32
que a su vez es un wrapper de un método implementado en código nativo
que hace los cálculos necesarios para producir un valor redondeado.
Como se observa entonces hay invocación a 3 métodos como mínimo lo cual
implica 3 cambios de contexto: el primero al llamar a ToInt32, luego al llamar a Decimal.FCallToInt32
y luego cuando este hace el wrapper a la función de código nativo,
hasta allí ya es mucho más lento que simplemente usar el cast (int),
ahora , la lógica usada internamente para convertir el tipo de 16
bytes al tipo de 4 bytes y tener en cuenta el redondeo y los casos
especiales como por ejemplo cuando el parámetro es null, convierte a esta función en una muchísimas veces más lenta que solo hacer (int).
2 - CONVERTIR DE TIPO FLOAT (SINGLE) A TIPO INT (INT32):
Si utilizas el operador de cast, es decir : (int)
Explicación básica:
El runtime lo que hará es simplemente tomar la parte entera del número descartando completamente la parte decimal.
Explicación más completa:
del tipo float es de 4 bytes mientras que el tipo int también es de 4 bytes (casi siempre), así que lo que sucede es que el runtime toma la parte entera del tipo float y la coloca en los 4 bytes enteros.
Si utilizas el Convert.ToInt32
Explicación básica:
Cuando el método estático ToInt32() recibe como parámetro un tipo de dato Single (float)
hace más que solo retornar la parte entera, de hecho redondea el
resultado al entero más cercano. Esto genera una sobrecarga adicional
que lo hace mucho más lento.
Explicación más completa:
ToInt32 cuando recibe un tipo Single (float) llama al método interno Convert.ToInt32 (si, de nuevo, pero llama al que recibe parámetro tipo double ya que la lógica para double es la misma que para Single (float))
que es finalmente quien resuelve la lógica para hacer el redondeo. Como
se observa entonces hay invocación a 2 métodos mínimo lo cual implica 2
cambios de contexto: el primero al llamar a ToInt32(Single), luego al llamar a ToInt32(double) que al final es que tiene en cuenta el redondeo y los casos especiales como por ejemplo cuando el parámetro es null, convierte a esta función en una muchísimas veces más lenta que solo hacer (int) pero comparativamente con el caso de Decimal no es tan lenta.
Conclusión: Si necesitas velocidad siempre usa operadores de cast, ejemplo: (int); si requieres aproximación y que te tengan en cuenta los casos especiales usa siempre Convert.