En las versiones anteriores a framework 2.0, era
absolutamente normal trabajar con colecciones de tipo object como base, entre ellas ejemplos como ArrayList, Queue, List,
etc., Esto traía dos problemas principales a los desarrolladores:
- Problemas de Conversion de Tipos.
- Problemas de rendimiento.
Vamos a ver de manera un poco más amplia cada uno de ellos.
Problemas de Conversión de tipos
Las colecciones anteriormente nombradas, al aceptar objetos
del tipo base object, no tenían
ningún tipo de control sobre los elementos que almacenaban, pudiendo almacenar objetos
de clases completamente diferentes y sin ningún tipo de concordancia ni
relación entre ellas. Por otra parte el compilador no podía realizar ninguna
comprobación de tipos por lo que este tipo de errores se daban en tiempo de
ejecución en vez de en tiempo de compilación. La única opción que existía era
crearse colecciones propias e implementar el tipo de restricciones.
Vamos a ver un ejemplo:
Como podemos observar en el ejemplo, no hemos tenido ningún
problema a la hora de instanciar el ArrayList, para añadir un ‘5.5’ que es un valor que sería de tipo double o decimal
y el compilador nos ha permitido compilar sin mostrar ningún tipo de error. Esto podría
haber sido mucha más bestia, ya que aquí se podrían haber hecho barbaridades
como esta:
El problema viene cuando intentamos hacer el sumatorio de
los valores de nuestra colección y tenemos que hacer el obligado casting a entero, al llegar a los datos no admitidos para la conversión,
se elevaría una excepción.
Este problema quedaría subsanado con el uso de Generics y
sus (Type Saves).
Como podemos ver en el pantallazo, el compilador ya nos
avisaría del error antes de compilar:
Problemas de rendimiento
El otro problema más significativo viene dado por la pérdida
de rendimiento derivado del boxing/unboxing.
El CLR permite crear tipos por referencia
class y tipos por valor structs. Los primeros guardan una
referencia al bloque de memoria que ocupa el objeto dentro del heap, y los segundos guardan un
espacio dentro de la pila.
El lugar de almacenamiento es completamente diferente para unos que para otros,
y en algunos casos viene a ser llamado la memoria lejana y la cercana.
El proceso de boxing,
consiste en envolver una estructura dentro de un objeto de tipo object:
A simple vista, parece una asignación normal, pero en el
proceso interno, el CLR
tiene que convertir el tipo por valor a un tipo por referencia, realizando el
cambio y transformando los datos de la pila
al heap, con el coste en rendimiento
que esto conlleva. Para un dato, puede parecer irrelevante, pero en colecciones
de miles de elementos la perdida de rendimiento es significativa.
El proceso de unboxing,
consiste justamente en el proceso contrario al anterior, es el paso en que
desempaquetamos el dato y lo transformamos de un tipo referencia a un tipo
valor:
Pues aquí finalizamos el repaso a los problemas que teníamos los desarrolladores de .NET antes de la aparición de Generics.
No hay comentarios :
Publicar un comentario