简体   繁体   English

如何使用lambda表达式创建扩展方法

[英]How to create extension methods with lambda expressions

Currently i am creating an extension method that accepts parameters. 目前我正在创建一个接受参数的扩展方法。 Using the below example, how could one convert this using lambda expressions? 使用下面的示例,如何使用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;
}

What are the pro/cons using lambda vs normal method parameters? 使用lambda vs normal方法参数的优缺点是什么?

Thanks 谢谢

One way you could change the sample to use lambda expressions is to use a filter. 更改样本以使用lambda表达式的一种方法是使用过滤器。

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

The biggest pro this gives you is flexbility. 这给你的最大专业是灵活性。 Instead of having a method which does date based filtering for calculation. 而不是使用基于日期过滤进行计算的方法。 You have a method with a flexible filter method for calculating percentages. 您有一种方法,使用灵活的过滤方法来计算百分比。

Did you want to replace the startDate and endDate parameters with a single lambda expression? 您是否要使用单个lambda表达式替换startDateendDate参数?

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

Your method is implicitly using lambda expressions already. 您的方法已经隐式使用lambda表达式。

When you say 当你说

trade.TradeTime >= startDate

What you're really saying is "given a Trade called " trade ", return a bool by evaluating the following: trade.TradeTime >= startDate ." 你真正说的是“给予Trade称为” trade “,通过评估以下内容返回一个booltrade.TradeTime >= startDate 。”

That is the definition of this lambda expression: 这是lambda表达式的定义:

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

And in fact, minus the declaration of expr , this is how you would express it if you were using the function composition syntax for LINQ instead of the query syntax. 事实上,减去expr的声明,如果你使用LINQ的函数组合语法而不是查询语法,这就是你表达它的方式。

If you don't want parameters, you can move the filtering outside. 如果您不想要参数,可以将过滤移到外面。

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

Then, it can be called like this: 然后,它可以像这样调用:

DateTime startDate, DateTime endDate

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

Continuing on Tim's answer , you could also provide a lambda to perform the calculation: 继续Tim的回答 ,您还可以提供lambda来执行计算:

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

Usage: 用法:

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

It's important to understand that Lambda expressions serve a different purpose than extension methods. 重要的是要理解Lambda表达式与扩展方法的用途不同。 Lambda expressions are used primarily as a compact syntax for defining a delegate implementation or function implementaion. Lambda表达式主要用作定义委托实现或函数实现的紧凑语法。 An added benefit of lambda expressions is that you can define event handlers and functions within the body of another function, useful if you have a simple function that is used only within a specific method. lambda表达式的另一个好处是,您可以在另一个函数体内定义事件处理程序和函数,如果您有一个仅在特定方法中使用的简单函数,则非常有用。 Just define the function using the Func<> or Action<> type with lamda syntax. 只需使用带有lamda语法的Func <>或Action <>类型定义函数。

I would recommend picking up a copy of Jon Skeet's C# In Depth. 我建议你拿一份Jon Skeet的C#In Depth。 It covers these topics in detail. 它详细介绍了这些主题。

Here's this function as a lambda expression 这是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;
            };
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM