Clases genéricas (parte primera, 1/n)
Genéricos C#: Clases, métodos,
delegados, predicados,...
Una de las
mejoras de .NetFramework que encontramos en .net son los tipos genéricos.
Nosotros podemos definir nuestras propias clases, ahora pensemos en que
necesitemos clases que van a contener atributos de los que no conocemos sus
tipos hasta que no los creamos. Una clase genérica o parametrizada podría
permitirme este tipo de diseño. Es muy útil para crear contenedores de datos y
por esto el .netframework ofrece todo un repertorio de clases genéricas como
listas, diccionarios,...
Así por
ejemplo tenemos la posibilidad de crear listas de cualquier cosa:
Puedo hacer
List<int> numerosPrimitiva = new
List<int>();
y también
List<Enemigo> listaNegra = new
List<Enemigo>();
Las listas
son una clase genérica (que encapsula arrays y algo más, así como muchas cosas
para manipular arrays). De la misma forma podemos crear estructuras del mismo
tipo. Como he dicho antes, muy útiles para generar contenedores de datos. Por
ejemplo para los que empezáis a estudiar las estructuras de datos ( un montón
de créditos ) una manera elegante de crear un Nodo de información podría ser
una clase genérica:
//Nodo de árbol binario
public class
Nodo<T>
{
public T dato;
public Nodo<T> hijoIzquierdo;
public Nodo<T>
hijoDerecho;
public Nodo(T _dato)
{
dato =
_dato;
}
}
Y ahora
podríamos hacer cosas como Nodo<int> = new Nodo<int>(5), y con el mismo código podemos hacer Nodo<Amigo> nodo= new
Nodo<Amigo>(new Amigo()); Pero claro, además si hacemos algo como public Class Enemigo : Amigo {...}, pudríamos hacer Nodo<Amigo> nodo = new
Nodo<Amigo>(new Enemigo()); Vamos que incluso haciendo uso de clases abstractas
puedo no sólo generalizar lo que va a contener mi clase genérica sino que
además puedo hacer que lo que contenga sea también genérico.
Con las
clases genéricas conseguimos evitar dos problemas, que el compilador tenga que
hacer boxing de elementos al tipo Object, en nuestro caso deberíamos
implementar fuciones de conversión del dato desde un Object, public Nodo
(Object obj) {…} y de Object a cualquier otro tipo, mejorando así el
rendimiento y el segundo problema que evitamos es el de seguridad, dado que una
vez que nuestro dato sea Object, no hay manera de saber en tiempo de
compilación qué contiene dicho dato, o por lo menos no es tarea del compilador.