viernes, 7 de mayo de 2010

Árboles de expresiones en C#



Características de C# 3.0 – Expresiones Lambda

En C# 3.0 la gente de Microsoft añadió muchas mejoras en el lenguaje, la mayoría inspirada en los lenguajes funcionales como Lisp, OCaml,… En particular hay dos que van de la mano: las expresiones lambda y los árboles de expresiones. Este primer artículo va a tratar de las expresiones lambda, así que recordemos que era un delegado y poco a poco veremos el porqué se añadieron todas estas nuevas características a C#.

Por ejemplo, queremos filtrar una lista de elementos T en base a un criterio pero queremos que el criterio sea modificable. Este “criterio” es una función que recibirá un T y devolverá un booleano indicando si el elemento cumple el criterio o no. En código tradicional de C# esto sería un delegado y sería algo como lo que sigue:

delegate bool Criteria(T element);



class Program

{

static List FilterList(List list, Criteria criteria)

{

List newList = new List();

foreach (T element in list)

if (criteria(element))

newList.Add(element);



return newList;

}



static bool CriteriaLessThan5(int intValue)

{

return intValue <> 5;

}



static void Main(string[] args)

{

List numbers = new List() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

List numbers2;



numbers2 = FilterList(numbers, CriteriaLessThan5);

foreach (int number in numbers2)

Console.WriteLine(number);



numbers2 = FilterList(numbers, CriteriaBiggerThan5);

foreach (int number in numbers2)

Console.WriteLine(number);



Console.ReadKey();

}

}


Árboles de Expresiones
Otra nueva característica mucho más “rara” de C# 3.0: son los árboles de expresiones. En algunos lenguajes, como Lisp, se permite manejar el código como si fueran datos y los datos como si fueran código. Los árboles de expresión son la forma que tiene C# de implementar esta funcionalidad (de forma algo limitada).

Por ejemplo, tenemos la expresión lambda:

num=> num <5;

Que devolvía si un número era menor que cinco o no. Expresado en forma de un delegado del tipo Func, el código sería:
Func(int,bool) f = num => num < 5;
Y la forma de poner lo mismo usando un árbol de expresiones es:
System.Linq.Expressions.Expression(Func(int, bool)) e = num => num < 5;
La diferencia entre Func y Expression es que f es una función que se puede ejecutar:
bool result = f(10);
Pero para ejecutar e tenemos que hacer lo siguiente:
bool result = e.Compile()(10);
Es decir: para ejecutar un árbol de expresiones primero tenemos que compilarlo (porque son datos que representan código, no código en sí) y una vez compilado ya podemos utilizar el resultado como si fuera un método normal. De forma gráfica, e internamente está representado por el árbol de este Blog

No hay comentarios:

Publicar un comentario