lunes, 27 de julio de 2009

Métodos de Extensión en Visual Studio 2008

Alguna vez, cuando estaba programando, me preguntaba si las cosas en la POO se podían hacer algo mas 'elegantes' y sin tanto rollo.

Un ejemplo común en la escuela es el clásico... 'De un arreglo de números enteros, decir cuáles son pares', y es típico que tenemos que hacer una función que me diga si es par o no, y mandar a llamar en un ciclo que recorra número por número...

Y me cuestionaba si se podía hacer algo como:

int[10] arrayNumeros;
arrayNumeros[0] = 4;
...
arrayNumeros[9]=62;

int[] arrayPares = arrayNumeros.Pares();

Quería hacer lo que está en color azul, que mandara a llamar a una función Pares y me regresara todos los pares en la función 'Pares', sin que tuviera que llamarla así:

int[] arrayPares = Pares(arrayNumeros);

Lo primero que se me vino a la cabeza es utilizar la Herencia, pero imagínense heredar de una clase solo para poder implementar un método.

Pues bien, la respuesta es que sí se puede hacer sin herencia en Visual Studio 2008 (con cualquiera de los lenguajes .NET, como C# o VB.NET), y el nombre de esta característica es 'Métodos de Extensión'.

Los métodos de extensión, son, como su nombre lo indica, métodos que se agregan a los tipos existentes en el .NET Framework o cualquiera que nosotros hayamos creado con cualquier lenguaje .NET, SIN NECESIDAD de hacer uso de la herencia para poder 'añadirle' alguna función o procedimiento (estos métodos se manejan de manera especial, pero se invocan como si se tratase de un método propio del tipo al que extendemos).

Lo explicaré utilizando el lenguaje C# (para mejor similitud con el añejo C++)

Primero, se define una clase estática donde estarán todas los métodos 'agregados' o extendidos, sin anidar esta clase con alguna otra.

por ejemplo:

namespace PruebaPares{

public static class Extensiones{

}

}

Después, se define el método o función que 'extienda' al tipo de: 'arreglos de enteros' (en nuestro caso), para esto el método también tiene que ser estático (Shared en VB.NET) y el primer parámetro debe ser el tipo del que se va a extender, en nuestro caso será un arreglo de enteros ( int[] ):

namespace PruebaPares{

public static class Extensiones{

public static int[] Pares(this int[] arreglo){

}

}

}

Observe que el tipo que devuelve es un arreglo de enteros con los resultados, es decir, con los números que son pares.

Voy a implementar este método utilizando LINQ, una tecnología, la cual merece un post (varios diría yo..) aparte:

namespace PruebaPares{

public static class Extensiones{

public static int[] Pares(this int[] arreglo){

IEnumerable resul = from p in arreglo
where (p % 2) == 0
select p;


return resul.ToArray();

}
}

}

Lo que hace esa consulta en LINQ es recorrer el arreglo y buscar los elementos que cumplen la condición en la cláusula 'WHERE', para quienes conozcan algo de SQL, verán esta sintaxis muy parecida. Bueno, después que filtra los resultados, lo convertimos en un arreglo de enteros y lo retornamos, así pues, un ejemplo para utilizar este método, y llamarlo de manera 'decente' sería así:



class Program
{


static void Main(string[] args){

int[] arrayEnteros = new int[]{2,3,4,5,7,8,9};

Console.WriteLine("Numeros pares");

foreach (int x in arrayEnteros.Pares()) {

System.Console.WriteLine("Numero :" + x);

}

System.Console.ReadLine();

}

}

1 comentario:

  1. Clásico ejemplo de cómo resolver de forma elegante algo que en principio parecería demasiado engorroso para lo que pide el enunciado.

    ResponderEliminar