2009-05-12 13 views
7

Actualmente estoy creando un método de extensión que acepta parámetros. Usando el siguiente ejemplo, ¿cómo podría uno convertir esto usando expresiones lambda?Cómo crear métodos de extensión con expresiones lambda

public static decimal ChangePercentage(this IEnumerable<Trade> trades, DateTime startDate, DateTime endDate) 
{ 
    var query = from trade in trades 
       where trade.TradeTime >= startDate 
       where trade.TradeTime <= endDate 
       orderby trade.TradeTime descending 
       select trade; 
    return (query.First().Value - query.Last().Value)/query.First().Value * 100; 
} 

¿Cuáles son los pro/cons utilizando los parámetros lambda vs método normal?

Gracias

+0

¿Qué quiere decir "usando expresiones lambda"? Como un filtro en lugar de startDate/endDate? Entonces vea la respuesta de Tim Robinson. De lo contrario, por favor elabora. – Lucas

+0

Esto tampoco estaba claro para mí. Sospecho que las respuestas de Tim y los demás probablemente sean en lo que estaba tratando. – mquander

+0

Sí, era un filtro que estaba buscando. No sabía cómo frasearlo correctamente. Por favor, modifique la pregunta como mejor le parezca :) –

Respuesta

8

Una forma de cambiar la muestra para usar expresiones lambda es usar un filtro.

public static decimal ChangePercentage(this IEnumerable<Trade> trades, Func<Trade,bool> pred) 
     { 
      var query = from trade in trades 
         where pred(trade); 
         orderby trade.TradeTime descending 
         select trade; 
      return (query.First().Value - query.Last().Value)/query.First().Value * 100; 
     } 

    someTrades.ChangePercentage(x => x.TradeDate >= startDate && x.TradeTime <= endDate); 

El mayor pro que esto le da es la flexibilidad. En lugar de tener un método que hace filtro basado en la fecha para el cálculo. Tienes un método con un método de filtro flexible para calcular porcentajes.

+0

+1 por ofrecer una solución flexible. –

2

Su método ya está implícitamente utilizando expresiones lambda.

Cuando dice

trade.TradeTime >= startDate 

Lo que en realidad está diciendo "dado un Trade llamado" trade "devuelven un bool mediante la evaluación de los siguientes: trade.TradeTime >= startDate."

Esa es la definición de esta expresión lambda:

Func<Trade, bool> expr = (trade => trade.TradeTime >= startDate); 

Y, de hecho, menos la declaración de expr, esta es la forma en que lo expresaría si estuviera usando la sintaxis de la composición de funciones para LINQ en lugar de la sintaxis de consulta

5

¿Desea reemplazar los parámetros startDate y endDate con una sola expresión lambda?

public static decimal ChangePercentage(this IEnumerable<Trade> trades, DateTime startDate, DateTime endDate) 
{ 
    return trades.ChangePercentage(trade => trade.TradeTime >= startDate 
     && trade.TradeTime <= endDate); 
} 

public static decimal ChangePercentage(this IEnumerable<Trade> trades, Func<Trade, bool> filter) 
    { 
     var query = from trade in trades 
        where filter(trade) 
        orderby trade.TradeTime descending 
        select trade; 
     return (query.First().Value - query.Last().Value)/query.First().Value * 100; 
    } 
0

Si no desea parámetros, puede mover el filtro al exterior.

public static decimal ChangePercentage(this IEnumerable<Trade> trades) 
{ 
    var query = trades.OrderByDescending(t => t.TradeTime); 

    if (query.Any()) 
    return (query.First().Value - query.Last().Value)/query.First().Value * 100; 
    else 
    return 0; 
} 

A continuación, se le puede llamar así:

DateTime startDate, DateTime endDate 

decimal answer = ChangePercentage 
(
    from trade in trades 
    where trade.TradeTime >= startDate 
    where trade.TradeTime <= endDate 
    select trade 
); 
0

Continuando Tim's answer, también se puede proporcionar una lambda para realizar el cálculo:

public static decimal ChangePercentage(
     this IEnumerable<Trade> trades, 
     Func<Trade, bool> filter, 
     Func<Trade, Trade, decimal> calc) 
    { 
     var query = from trade in trades 
        where filter(trade) 
        orderby trade.TradeTime descending 
        select trade; 
     return calc(query.First(), query.Last()); 
    } 

Uso:

trades.ChangePercentage(
     trade => (trade.TradeTime >= startDate && trade.TradeTime <= endDate), 
     (t1, t2) => (t1.Value - t2.Value)/t1.Value * 100 
    ); 
0

Es i Es importante entender que las expresiones Lambda tienen un propósito diferente al de los métodos de extensión. Las expresiones Lambda se usan principalmente como una sintaxis compacta para definir una implementación de delegado o implementación de función. Un beneficio adicional de las expresiones lambda es que puede definir manejadores de eventos y funciones dentro del cuerpo de otra función, útil si tiene una función simple que se usa solo dentro de un método específico. Simplemente defina la función utilizando el tipo Func <> o Acción <> con sintaxis lamda.

Yo recomendaría recoger una copia de C# In Depth de Jon Skeet. Cubre estos temas en detalle.

Aquí está esta función como una expresión lambda

private void Form1_Load(object sender, EventArgs e) 
     { 
      //signature of our function 
      Func<IEnumerable<Trade>, DateTime, DateTime, decimal> changePercentage = null; 

      //function implemented using lambda expression syntax 
      changePercentage += (trades, startDate, endDate) => 
      { 
       var query = from trade in trades 
          where trade.TradeTime >= startDate 
          where trade.TradeTime <= endDate 
          orderby trade.TradeTime 
          descending 
          select trade; 
       return (query.First().Value - query.Last().Value)/query.First().Value * 100; 
      }; 
     } 
Cuestiones relacionadas