sábado, 8 de mayo de 2010

Arboles de Expresiones en C#

Una expresión lambda es una función anónima que puede contener expresiones e instrucciones y se puede utilizar para crear delegados o tipos de árboles de expresión.

Todas las expresiones lambda utilizan el operador lambda = >, que se lee como "va a". El lado izquierdo del operador lambda especifica los parámetros de entrada (si existe alguno), mientras que el lado derecho contiene el bloque de expresiones o instrucciones. La expresión lambda x => x * x se lee "x va a x veces x". Esta expresión se puede asignar a un tipo de delegado del siguiente modo:

Cuando se utiliza la sintaxis de método para llamar al método Where en la clase Enumerable (como se hace en LINQ to Objects y LINQ to XML), el parámetro es un tipo delegado System.Func(Of T, TResult). Una expresión lambda constituye la manera más práctica de crear ese delegado. Cuando se llama al mismo método en, por ejemplo, la clase System.Linq.Queryable (como se hace en LINQ to SQL), el tipo de parámetro es System.Linq.Expressions.Expression, donde Func es cualquier delegado de Func que tenga hasta cinco parámetros de entrada. De nuevo, una expresión lambda constituye una manera muy concisa de construir ese árbol de expresión. Las expresiones lambda permiten que las llamadas a Where tengan un aspecto similar, aunque, de hecho, el tipo de objeto creado desde la expresión lambda sea diferente.

Los árboles de expresiones representan el código de nivel del lenguaje en forma de datos. Los datos se almacenan en una estructura con forma de árbol. Cada nodo del árbol de expresión representa una expresión, por ejemplo, una llamada al método o una operación binaria, como x <>.

En la ilustración siguiente se muestra un ejemplo de una expresión y su representación en forma de un árbol de expresión. Las diferentes partes de la expresión tienen un color distinto para hacerlas coincidir con el nodo correspondiente del árbol de expresión. También se muestran los diferentes tipos de los nodos del árbol de expresión.

En el ejemplo de código siguiente se muestra cómo el árbol de expresión que representa la expresión lambda num => num <> (C#) o Function(num) num <> (Visual Basic) se puede descomponer en partes.




Generar árboles de expresiones

El espacio de nombres System.Linq.Expressions proporciona una API para la compilación manual de árboles de expresiones. La clase Expression contiene métodos de generador estáticos que crean nodos del árbol de expresión de tipos específicos, por ejemplo, un objeto ParameterExpression, que representa una expresión de parámetro con nombre, o un objeto, MethodCallExpression, que representa una llamada a un método. ParameterExpression, MethodCallExpression y los demás tipos de árboles de expresiones específicos de la expresión se definen también en el espacio de nombres System.Linq.Expressions. Estos tipos se derivan del tipo abstracto Expression.

El compilador también puede generar un árbol de expresión. Un árbol de expresión generado por el compilador siempre tiene como raíz un nodo de tipo Expression<TDelegate>; es decir, su nodo raíz representa una expresión lambda.

En el ejemplo de código siguiente se muestran dos mecanismos para crear un árbol de expresión que representa la expresión lambda num => num <> (C#) o Function(num) num <> (Visual Basic).

Para mi lo mas interesante de los arboles de expresiones es que en vez de dejar que el compilador los genere automaticamente, podemos construirlos nosotros manualmente, aunque puede ser algo tedioso.




Bibliografía:

http://kartones.net/blogs/jadengine/archive/2009/03/31/193-rboles-de-expresiones.aspx
http://msdn.microsoft.com/es-es/library/bb397687%28VS.90%29.aspx
http://msdn.microsoft.com/es-es/library/bb397951%28VS.90%29.aspx
http://www.elguille.info/NET/futuro/firmas_octavio_ArbolesExpresiones.htm

3 comentarios:

  1. muy cierto, lo más interesante es que el programador puede manipular los árboles a su conveniencia! Eso es muy útil para trabajar libremente con el código

    ResponderEliminar
  2. Otro que no tiene ni puta idea. Bueno, salvo lo del Copy&Paste, que eso si lo domina...

    ResponderEliminar
  3. Otro que no tiene ni puta idea. Bueno, salvo lo del Copy&Paste, que eso si lo domina...

    ResponderEliminar