Как создать методы расширения с лямбда-выражениями - PullRequest
7 голосов
/ 12 мая 2009

В настоящее время я создаю метод расширения, который принимает параметры. Используя приведенный ниже пример, как можно преобразовать это, используя лямбда-выражения?

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;
}

Каковы плюсы / минусы, использующие лямбда-параметры против нормальных параметров метода?

Спасибо

Ответы [ 6 ]

8 голосов
/ 12 мая 2009

Один из способов изменить образец для использования лямбда-выражений - это использовать фильтр.

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);

Самый большой профессионал, который это дает, - это гибкость. Вместо того, чтобы иметь метод, который делает фильтрацию на основе даты для расчета. У вас есть метод с гибким фильтром для расчета процентов.

5 голосов
/ 12 мая 2009

Вы хотели заменить параметры startDate и endDate одним лямбда-выражением?

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;
    }
2 голосов
/ 12 мая 2009

Ваш метод уже неявно использует лямбда-выражения.

Когда вы говорите

trade.TradeTime >= startDate

То, что вы на самом деле говорите, «дано Trade, называемое« trade », верните bool, оценив следующее: trade.TradeTime >= startDate

Это определение этого лямбда-выражения:

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

На самом деле, минус объявление expr, это то, как вы бы это выразили, если бы использовали синтаксис композиции функций для LINQ вместо синтаксиса запроса.

0 голосов
/ 12 мая 2009

Важно понимать, что лямбда-выражения служат иной цели, чем методы расширения. Лямбда-выражения используются в основном как компактный синтаксис для определения реализации делегата или реализации функции. Дополнительным преимуществом лямбда-выражений является то, что вы можете определять обработчики событий и функции в теле другой функции, что полезно, если у вас есть простая функция, которая используется только внутри определенного метода. Просто определите функцию, используя тип Func <> или Action <> с синтаксисом lamda.

Я бы порекомендовал взять копию C # In Depth. В них подробно рассматриваются эти темы.

Вот эта функция как лямбда-выражение

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;
            };
        }
0 голосов
/ 12 мая 2009

Продолжая Ответ Тима , вы также можете указать лямбду для вычисления:

    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());
    }

Использование:

    trades.ChangePercentage(
        trade => (trade.TradeTime >= startDate && trade.TradeTime <= endDate), 
        (t1, t2) => (t1.Value - t2.Value) / t1.Value * 100
    ); 
0 голосов
/ 12 мая 2009

Если вам не нужны параметры, вы можете переместить фильтрацию наружу.

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;
}

Тогда это можно назвать так:

DateTime startDate, DateTime endDate

decimal answer = ChangePercentage
(
  from trade in trades
  where trade.TradeTime >= startDate
  where trade.TradeTime <= endDate
  select trade
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...