可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Currently i am creating an extension method that accepts parameters. Using the below example, how could one convert this using lambda expressions?
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?
Thanks
回答1:
One way you could change the sample to use lambda expressions is to use a filter.
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.
回答2:
Did you want to replace the startDate
and endDate
parameters with a single lambda expression?
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;
}
回答3:
Your method is implicitly using lambda expressions already.
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
."
That is the definition of this lambda expression:
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.
回答4:
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
);
回答5:
Continuing on Tim's answer, you could also provide a lambda to perform the calculation:
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
);
回答6:
It's important to understand that Lambda expressions serve a different purpose than extension methods. Lambda expressions are used primarily as a compact syntax for defining a delegate implementation or function implementaion. 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. Just define the function using the Func<> or Action<> type with lamda syntax.
I would recommend picking up a copy of Jon Skeet's C# In Depth. It covers these topics in detail.
Here's this function as a lambda expression
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;
};
}