Nota del autor

Si la entrada que estás leyendo carece de imágenes, no se ve el vídeo que teóricamente lleva incrustado o el código fuente mostrado aparece sin formato, podéis conocer los motivos aquí. Poco a poco iré restableciendo la normalidad en el blog.
Este blog es un archivo de los artículos situados previamente en Lobosoft.es y ha dejado de ser actualizado. Las nuevas entradas pueden encontrarse en www.lobosoft.es. Un saludo,
Lobosoft.

martes, 26 de febrero de 2008

Expresiones Lambda en C#

Ya he hablado en otras ocasiones sobre la incorporación de las expresiones lambda al .Net Framework a partir de su versión 3.0. Este tipo de expresiones, en las que profundizaremos hoy, proporcionan al framework el soporte necesario para el uso de LINQ como lenguaje de consulta casi, diríamos, universal. Lo primero que llama la atención al ver la implementación de las expresiones lambda en .Net es que, de haber aparecido antes, no habrían sido necesarios los métodos anónimos que se incorporaron en la anterior versión del framework (.Net 2.0). Es más, en cierto modo constituyen -entre otras mejoras- un embellecimiento del código y un (permítasenos la licencia de llamarlo así) encapsulamiento del método anónimo y del delegado que lo incluye. Esta relación, y cómo se definen las expresiones lambda, será el tema principal de la entrada de hoy.


En el cálculo del interés simple, dentro del campo de las matemáticas financieras, entran en juego una serie de ecuaciones que deseamos implementar en nuestro código.


Interés = Capital * Tiempo * Tasa de interés
Valor Futuro = Capital * (1 + Tasa * Tiempo)
Capital = Valor Futuro * (1+ Tasa * Tiempo) -1

Si deseáramos implementar estas funciones mediante el uso de métodos anónimos, deberíamos hacerlo a través de un delegado. Por ejemplo, la función que define el Interés podría implementarse como sigue:


[csharp]
private static double MiInteres(double C, int t, float i)
{
return ((C * t) * i);
}
[/csharp]

Para poder asignarla a un delegado, deberíamos tener definido un delegado con su misma firma:


[csharp]public delegate double Func(double C, int t, Single i);[/csharp]

La asignación, entonces, sería automática:


[csharp]Func miInteres1 = MiInteres;[/csharp]

Sin embargo, los métodos anónimos nos brindan un método más compacto y elegante para obtener el mismo resultado:


[csharp]Func miInteres2 = delegate(double C, int t, Single i) { return C * t * i; };[/csharp]

La definición de Func, incluido en el espacio de nombres System.Linq como tipo genérico de delegado, es la que sigue (para un ejemplo con 0, 1 y 2 argumentos):


[csharp]
public delegate TResult Func();
public delegate TResult Func(T1 arg1);
public delegate TResult Func(T1 arg1, T2 arg2);
[/csharp]

Visto esto, ¿cómo podríamos realizar la implementación de nuestras funciones financieras usando expresiones lambda? Vuelvo a incidir en la cercanía de dichas expresiones con los lenguajes funcionales y en que, debido a esta característica, su declaración será compacta y precisa. Comencemos con la misma función que nos ha ocupado hasta este momento, la del cálculo del interés simple. Recordemos que esta función estaba definida como

Interés = Capital * Tiempo * Tasa de interés

La expresión lambda equivalente será
[csharp]
public static Func Interes = (C, t, i) => (C * t * i);
[/csharp]

Como vemos, el C# de los .Net Frameworks 3.0 y 3.5 incluye mediante las expresiones lambda una sintaxis mucho más clara y concisa que el que se conseguía mediante el uso de los métodos anónimos. Una posible implementación de las ecuaciones implicadas en el cálculo del interés podría ser la siguiente:


[csharp]
public static class InteresSimple
{
public static Func Interes =
(C, t, i) => (C * t * i);

public static Func ValorFuturo =
(C, t, i) => (C * (1 + i * t));

public static Func Capital =
(VF, t, i) => (VF * Math.Pow((1 + i * t), -1));
}
[/csharp]

Entre las ventajas que nos aportará el uso de las expresiones lambda frente al de métodos anónimos y delegados se encuentra no sólo la simplicidad y limpieza sintáctica de la expresión, sino también la posiblidad de usar bloques de código como datos (algo inherente a estas expresiones e imposible de conseguir mediante los métodos anónimos), una característica en la que profundizaremos en otra ocasión.

No hay comentarios:

Publicar un comentario