Friday, June 09, 2006

Generics

Dandole una mirada al Framework 2.0, este viene con el tema de los tipos genéricos. Básicamente una forma de expresar un tipo, de una manera tal que permita trabajar con cualquier tipo de dato. Por ejemplo:

Si queremos definir un tipo, llamado stack (pila), no generico tenemos algo como esto:

class Stack {
private object[] store;
private int size;
public Stack()
store=new object[10]; size=0;
}

Ahora si lo quieren genérico, aqui está lo interesante del asunto:

class Stack {
private T[] store;
private int size;
public Stack()
store=new T[10]; size=0;
}

Fijense que sería como una especie de plantilla, para la cual definiremos cualquier tipo de dato, consiguiendo una clase stack de tipos genéricos. En el caso no genérico tenemos por ejemplo un arreglo store como tipo object, lo que supone recibir cualquier tipo de datos, pero incurriendo obviamente en la costosa operación de boxing y unboxing.
Por el contrario, con nuestro modelo genérico el arreglo store, está habilitado para ser del tipo que le definamos sin incurrir en operaciones de boxing y unboxing.

Hasta el momento el ejemplo nos muestra que podemos definir tanto Clases como sus miembros de tipo genérico.

Pero ahora veamos la implementación de los métodos de ingreso y sacada de elementos de la pila en el modo no genérico:

public void Push(object x) {
if (size>=store.Size) {
object[] tmp = new object[size*2];
Array.Copy(store,tmp,size);
store = tmp;
}
store[size++] = x;
}
public object Pop() {
return store[--size];
}

Es de observar el uso de object como forma de recibir cualquier tipo de dato, pero si le pasamos tipos primitivos, incurrimos en la no bienvenida operación de box, por ejemplo, compilemos lo anterior y analicemos un poco el IL generado.



En la ventana generada gracias al ILDASM.EXE en la línea IL_000a: box, se aprecia una clara llamada a una operación de box. Ahora imaginense esto ocurriendo por cada elemento que entre a la pila de tipo primitivo, en este caso un entero, que deberá ser casteado a Object.

Ahora observermos la versión genérica mirada a través de la lupa del ILDASM:

public void Push(T x)
{
if (size>=store.Length)
{
T[] tmp = new T[size*2];
Array.Copy(store,tmp,size);
store = tmp;
}
store[size++] = x;
}

public T Pop()
{
return store[--size];
}



Alguien me puede ayudar a buscar la operación de Box que no la veo. Si señores, una ventaja de Generics vista en puro C# convertido a IL.

Como se puede observar, igualmente nuestra clase genérica puede también tener Métodos genéricos, el caso de Pop() y métodos no genéricos que reciben tipos genéricos el caso de Push().

Este ejmplo lo tome del artículo
http://research.microsoft.com/projects/clrgen/generics.pdf
y quise comprobar a través del ILDASM, para ver de cerca una de las ventajas claras de Generics Types.

No comments: