martes, 29 de enero de 2008

Cuando se habla de .NET 3 lo primero que salta a la mente es LINQ. Todo el mundo habla de LINQ como una maravilla de la técnica, y en realidad es bastante interesante.
Imaginemos que tenemos la clase Persona:

class Persona
{
string m_nombre;
string m_apellido;
public Persona(string nombre, string apellido)
{
m_nombre = nombre;
m_apellido = apellido;
}
public string Nombre { get { return m_nombre; } }
public string Apellido { get { return m_apellido; } }
public override string ToString()
{
return Nombre + " " + Apellido;
}
}

y tenemos una colección de personas:

List< Persona > personas = new List< Persona >();
personas.Add(new Persona("Rodrigo", "Rojas"));
personas.Add(new Persona("Armando","Fuentes"));
personas.Add(new Persona("Lucia", "Wong"));
personas.Add(new Persona("Maritza","Rojas"));

usando LINQ podríamos buscar a todos los "Rojas" asi:

var a = from p in personas
where p.Apellido == "Rojas"
select p;
foreach (Persona per in a)
{
Console.WriteLine("{0}", per);
}

Ya se que también podría preguntar en el ciclo, pero es evidente que se ve cool por un lado, por otro lado el ejemplo es idiotamente simplista pero las consultas que se construyen con LINQ pueden ser bastante mas complejas, sin contar con el hecho de que separar el ciclo de la selección tiene la ventaja de poder usar el mismo ciclo en selecciones diferentes, algo que ya se hace en .NET 2 con el yield return pero que aqui se lleva mas lejos con este mecanismo que permite estandarizar una buena parte de las búsquedas sobre colecciones, algo tan común en cualquier programa.

Con todo esto del LINQ no se notan los mecanismos verdaderamente poderosos que permiten que exista, estos son los métodos de extensión (extension methods) y el patrón consulta (query expression pattern).

Los métodos de extensión no son mas que una nueva forma de llamar a un método estático que permite que la invocación sea , quizas , mas clara. Por ejemplo: Vamos a suponer que queremos en el código anterior obtener el nombre de una manera mas ... formal, en vez de nombre+apellido, queremos apellido+","+nombre, pero supongamos que esa clase no fue escrita por nosotros y no podemos ir para atrás y modificarla por los motivos que fueran. Lo mas probable es que creemos un método estático en alguna clase, que si además solo hace eso también será estática, y que nos haga el trabajo, algo asi:

static class Nombrar
{
public static string NombreFormal(Persona per)
{
return per.Apellido + ", " + per.Nombre;
}
}

el ciclo anterior quedaría asi:

foreach (Persona per in a)
{
Console.WriteLine("{0}", Nombrar.NombreFormal(per));
}

Ahora convertimos NombreFormal en método de extensión con un ligero cambio:

static class Nombrar
{
public static string NombreFormal(this Persona per)
{
return per.Apellido + ", " + per.Nombre;
}
}

y el ciclo se puede escribir asi:

foreach (Persona per in a)
{
Console.WriteLine("{0}", per.NombreFormal());
}

Es todo una cuestión de imagen, pero queda sin duda mucho mejor.

Y ahora entra el patrón consulta. Este dice que si una clase implementa ciertos métodos entonces puede usarse en una expresión de consulta, como la que vimos al inicio, estos métodos son enrte otros Select, Where, Join, OrderBy , entre otros. Y que es LINQ ? Pues LINQ no es mas que la implementación de esos métodos para cualquier tipo que implemente la interface System.Collections.Generic.IEnumerable< t > por eso es que se puede usar con cualquier colección, hasta con un arreglo. Lo poderoso de esto es que uno puede hacer su propio LINQ, es decir, implementar estos métodos para hacer que nuestras clases se comporten como orígenes de datos "consultables".

No hay comentarios: