Jair Cazarin Villanueva jair.cazarin@gmail.com http://jaircazarin.spaces.live.

com

LINQ: Language Integrated Query
LINQ [1] es una extensión a los lenguages del .NET Framework, C# y Visual Basic .NET, planeada para ser lanzada con Orcas [2] en este año. El objetivo de LINQ es el de proveer a este par de lenguages de programación la posibilidad de hacer queries nativamente desde el lenguaje, esto quiere decir ya no lidiar con SqlCommand, SqlDataReader, y demás objetos. Para muestra, un ejemplo dónde se obtienen de un array de enteros los que son menores a 5: public void Linq1() { int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; var lowNums = from n in numbers where n < 5 select n; Console.WriteLine("Numbers < 5:"); foreach (var x in lowNums) { Console.WriteLine(x); } } Esto quiere decir, que LINQ no solo fue hecho para atacar el problema del miss-match entre las bases de datos relacionales y los lenguajes de programación orientados a objetos, sino que funciona para cualquier clase que implemente la intefaz IEnumerable [3] (Cualquier collection actualmente lo hace) e incluso también está hecho para proporcionar todo el poder de Xquery [4] y Xpath [5] pero built-in en el lenguaje.

Para lograr todo esto LINQ utiliza las siguientes características del framework (Que también son nuevas):

● ● ● ● ●

Anonymous Types. Extension Methods. Lambda Expressions. Expression Trees. Standard Query Operators.

Anonymous Types Los anonymous types son un feature del .Net Framework 3.0 que permite crear tuplas ó tipos de datos inexistentes automáticamente en tiempo de compilación. Pareciera complicado, pero es bastante sencillo. Lo que sucede es que si necesitamos un objeto que contenga las propiedades “Nombre” y “Apellido”, por ejemplo para obtener los nombres y apellidos de una lista de trabajadores guardada en una base de datos en SQL Server, normalmente lo que tendríamos que hacer es crear nuestra class ó struct Trabajador, con estas 2 propiedades. Lo que nos permiten los Anonymous Types, es solo asignar las propiedades que queramos a un object initializer con el keyword var y el compilador automáticamente creará esta clase, con sus respectivas properties en tiempo de compilación. Por ejemplo: var p1 = new {Name = "Jair", LastName = "Cazarin"}; Y nuestro compilador de C# 3.0 nos producirá algo así: class __Anonymous1 { private string name ; private string lastName; public string Name{ get { return name; } set { name = value ; } } public string LastName{ get { return lastName; } set { lastName= value ; } } } __Anonymous1 p1 = new __Anonymous1(); p1.Name = "Jair"; p1.LastName = "Cazarin"; Extension Methods Seguramente se preguntaron, cuando vieron el primer ejemplo, de dónde salieron los keywords select, y where si un array no tiene estos métodos, y la respuesta es usando Extension Methods. Y el objetivo de los mismos es precisamente ese, el de extender métodos y clases ya existentes. Ahora deben estar pensando, y no para eso era la herencia? Así es, pero uno de los problemas es que cuando no se tiene acceso al código fuente, se vuelve muy limitado ya que muchas clases restringen la herencia o a ciertas propiedades (Sealed Class [6]). Para hacerlo solo necesitamos usar el keyword this en el argumento del método y que el método sea static. Ejemplo: static class Program { static void Main(string[] args) { string s = "Hello, world"; s.Print(); } static void Print(this string s) { Console.WriteLine(s); } } En este caso estamos añadiendole la funcionalidad de Print a un string. Lambda Expressions Las lambda Expressions están basados en el Lambda Calculus [7] el cual viene desde mucho tiempo atrás en los inicios de la computación y son una característica muy importante de los lenguajes funcionales como Lisp [8], fue creado por Alonzo Church y Stephen Cole Kleene (Si, el de la cerradura de Kleene). Lo que nos proporcionan las Lambda Expressions en C# son una forma más limpia de declarar lo que lanzó Microsoft en .net 2.0: Anonymous Methods. Y para LINQ nos sirve para hacer expresiones muy poderosas y elegantes dentro del statement where, solo como un ejemplo. Para tener una idea más clara de lo que son, supongamos como se haría un delegate con Anonymous Methods:

delegate T Func<T>(T t); Func<int> funcDel = delegate(int x) { return x + x; }; Y con lambda expressions sería así: Func<int> lambda = x => x + x; Mucho más sencillo, y para llamarlo solo necesitamos poner: lambda(1); por ejemplo. Expression Trees Esto es uno de los features más complicados, pero para los que han programado alguna vez en LISP no necesitan ninguna explicación. Y se basa en el hecho de manejar expresiones (Lambda Expressions) como estructuras de datos en lugar de código ejecutable y añade un gran poder a las Lambda Expressions. Como vimos, un Lambda expression se puede declarar como código ejecutable y se puede usar simplemente como una función más. Sin embargo cuando se usan mediante System.Query.Expression (Expression Tree) el delegate no es compilado en código ejecutable sino como datos que son convertidos y compilados en el delegate original. Para usarla se deben compilar e invocar explicitamente en la aplicación. Func<int,int> f = x => x + 1; Expression<Func<int,int>> expression = x => x + 1 Para usarla: var originalDelegate = expression.Compile(); var three = originalDelegate.Invoke(2); En el caso de LINQ sirve para poder llamar a funciones dentro de queries. Standard Query Operators Por último está el Standard que define las operaciones que se pueden hacer, mediante el uso de Extension Methods, y que nos proporciona cosas como esta: int[] nums = new int[] {1,2,3,4,5,6,7,8,9}; double avg = nums.Average(); Para obtener la lista completa del Standard, descargar el archivo Standar Query Operator Documentation [9] del sitio de Microsoft.

Muchos personas piensan que los lenguajes de .net principalmente C# cada vez se está volviendo más tipo C++, pero yo al contrario pienso que C# se está volviendo más perfecto cada vez que sacan una nueva versión. En este caso la integración de query-syntax dentro del lenguaje se me hace extraordinario y que ningún lenguaje hasta ahorita ha hecho. Ya para finalizar algunos ejemplos más: publicvoid Linq() { List products = GetProductList();List customers = GetCustomerList(); var productFirstChars = from p in products select p.ProductName[0]; var customerFirstChars = from c in customers select c.CompanyName[0]; var commonFirstChars = productFirstChars.Intersect(customerFirstChars);

Console.WriteLine("Common first letters from Product names and Customer names:"); foreach (var ch in commonFirstChars) { Console.WriteLine(ch); } } publicvoid Linq() { int[] factorsOf300 = { 2, 2, 3, 5, 5 }; var uniqueFactors = factorsOf300.Distinct(); Console.WriteLine("Prime factors of 300:"); foreach (var f in uniqueFactors) { Console.WriteLine(f); } } public void Linq() { string[] words = { "cherry", "apple", "blueberry" }; var sortedWords = from w in words orderby w select w; Console.WriteLine("The sorted list of words:"); foreach (var w in sortedWords) { Console.WriteLine(w); } } Para descargarlo [10]. Y recomiendo mucho ver este video en Channel 9 del genio detrás de esto, Anders Hejlsberg [11]

Referencias: [1] http://msdn2.microsoft.com/en-us/netframework/aa904594.aspx [2] http://msdn2.microsoft.com/en-us/vstudio/aa700830.aspx [3] http://msdn2.microsoft.com/en-us/vstudio/aa700830.aspx [4] http://aspnet.4guysfromrolla.com/articles/071603-1.aspx [5] http://msdn2.microsoft.com/en-us/library/ms256453.aspx [6] http://www.csharphelp.com/archives/archive158.html [7] http://en.wikipedia.org/wiki/Lambda_calculus [8] http://en.wikipedia.org/wiki/Lisp_programming_language [9] Standard Query Operator Documentation [10] Download [11] http://channel9.msdn.com/showpost.aspx?postid=114680