Generics vs Collections en .NET 2.0

[Utilización de Generics en .NET 2.0 versus las clásicas Collections]

 

Fecha: 14/Jul/2005 (13 de Julio del 2005)
Autor: Javier Carrillo (jdcarriat@hotmail.com, javierdcarrillo@gmail.com)

 


A continuación veremos un poco sobre las "nuevas" clases del espacio de nombres System.Collections.Generics de .NET 2.0 y cómo se diferencian de las existentes en System.Collections.

Las clases "genericas" son casualmente para colecciones "genericas", la idea es darle a la colección un "Tipo inicializador", algo que le diga qué tipos de objetos contendrá y que (gracias a la RAD de .NET), es funcional tanto en el momento de programar (y compilación), como al ejecutarse (me refiero al uso de intellisense y validaciones del compilador).
El problema en versiones anteriores al .NET 2.0 era que para poder utilizar colecciones uno podía o bien utilizar las clases del espacio de nombres System.Collections o construir las propias....pero por qué???..
Bueno, lo que pasaba era que antes (en .NET 1.1 / 1.0), las colecciones que nos ofrecía el .NET Framework almacenaban implícitamente instancias de object, de modo que no se podría garantizar el establecimiento inflexible de tipos (por ejemplo a mi colección de empleados le podía agregar un número). La conversión inflexible de tipos es hacer que sólo un tipo específico sea manejado (en este caso en las colecciones). Uno podía evitar esto haciendo una clase derivada de CollectionBase (por ejemplo...) e implementar nuestra propia inflexibilidad de tipos,...sin embargo..las ventajas no eran muchas, ...dado que si bien al momento de utilizar la colección podíamos "tener garantía de tipos", nuestra clase derivada CONTINUABA HACIENDO "CAST" internos desde System.Object a la clase con la que trabajada nuestra colección,...lo que no era nada bueno para la performance durante la ejecución.
Ahora en .NET 2.0,..tenemos las clases Generics...éstas clases nos permiten poner (como indique antes), un inicializador de tipo a la colección (por ejemplo List<T>), donde T es una Clase (ojo ..no una instancia de Clase...vean el ejemplo....). la ventaja es que podemos acceder directamente a miembros de la Clase, sin hacer ningún tipo de casting, y algo aún mejor LA COLECCION REALMENTE ALMACENA INSTANCIAS de la CLASE INDICADA, de modo que NO SE REALIZA NINGUNA CONVERSION INTERNA....lo que OBVIAMENTE...mejora la performance...:D :D :D
Ahora bien,...si además quieres definir código personalizado para tu colección,...pero no quieres hacer cast tras cast...(al heredar de CollectionBase,..como ocurría en .NET 1.1)....puedes derivar de las clases Generic (que atinadamente no son Sealed - NotInheritable en VB)....
En este ejemplo he definido cuatro colecciones y las he puesto como propiedades de una clase Empresa, éstas colecciones se basan en 4 modelos:

  1. Colección utilizando el clásico ArrayList de .NET 1.1
  2. Colección utilizando la "nueva" clase List (de generics) de .NET 2.0
  3. Colección utilizando una clase derivada de CollectionBase (que agrega la inflexión de tipos).
  4. Colección utilizando una clase derivada de List (que agrega personalización a la inflexión heredada).

El ejemplo lo he desarrollado con la Version Team System de Visual Studio .NET 2005 Beta 2, pero si tienes el framework 2.0, no interesa si lo haces a través de alguna de las versiones Express (para los curiosos que se pregunten por la versión o interfaz de la RAD).

Clases definidas en el ejemplo

Para este ejemplo he creado Dos clases: Empresa y Empleado, definiendo que una Empresa puede tener a varios Empleados. Para implementar esta "relación de clases", empresa tiene una colección de Empleado, la que se ha implementado a través de las cuatro formas descritas arriba.

Aquí vemos cómo no existe establecimiento inflexible de tipos al agregar una instancia de Empleado a la colección definida como ArrayList (o sea, le DEBERÍA agregar un empleado, pero como ArrayList utiliza instancias de object, le podría agregar un número entero).

 

Aquí vemos cómo el implementar la colección con la clase List del espacio de nombres System.Collections.Generic nos brinda la tan deseada inflexibilidad de tipos, sin que tengamos que escribir código adicional que la verifique, pues el inicializador de List define en tiempo de programación y ejecución el tipo de las instancias que contendrá List.

 

Aquí vemos el implementar nuestra propia clase derivada de CollectionBase nos permite tener flexibilidad de tipos, sin embargo internamente la clase SIGUE ALMACENANDO instancias de Object, por lo que se siguen haciendo conversiones desde Object a Empleado.

Aquí vemos cómo el implementar nuestra propia clase derivada de List (en el espacio de nombres System.Collections.Generic nos permite, además de tener la inflexibilidad de tipos heredada y listita, implementar código personalizado (como la obtención a través del nombre del empleado además del índice de su posición en la colección....claro, eso también lo podías hacer heredando de CollectionBase,,claro!!!)...pero con la ENORME VENTAJA de que ahora sí, la colección REALMENTE ALMACENA INSTANCIAS DE Empleado, nos más conversiones,...lo que se traduce..en mejor performance..:D :D

Finalmente....

Este ha sido un pequeño ejemplo de cómo utilizar Generics, disponibles en .NET 2.0 y su diferencia y ventajas sobre Collections (que aún siguen disponibles...). En el archivo adjunto encontrarás el código fuente...lamento pero sólo lo hicen en C#,..no por preferencias, sino que como ven, es algo tarde y tenía trabajo al día siguiente...No dejes de mirar el código adjunto, pues tiene muchas mejores explicaciones.
El código del ejemplo está en el archivo adjunto...espero que te sea muy útil !!! :D :D..Saludos!!!
Javier Carrillo Atanacio
Célula .NET USIL...

 


Espacios de nombres usados en el código de este artículo:

System
System.Collections
System.Collections.Generic

 


Fichero con el código de ejemplo: JavierCarrillo_EjemploGenerics_CS.zip - 50 KB


ir al índice