Está en la página 1de 4

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