我有两个类似的函数,我希望重构以删除重复:
IEnumerable<TotalType> GetTotalForMonths(string id, DateTime lastTotalDate)
{
for (int i = 0; lastTotalDate.AddMonths(i + 1) <= DateTime.Now; i++)
{
var totalStartDate = new DateTime(lastTotalDate.AddMonths(i).Year, lastTotalDate.AddMonths(i).Month, 1);
var totalEndDate = totalStartDate.AddMonths(1);
var total = this.GetTotal(id, totalStartDate, totalEndDate);
yield return new TotalType(id, total, new TimeInterval(totalStartDate, totalEndDate));
}
}
其他人几天都做同样的事情。我希望传递一个代表来通用特定的持续时间(天,月等)。我尝试传入Func<DateTime, DateTime> addTime
,这很有效,除了我不想指定addTime的arg值。
建议?
答案 0 :(得分:2)
我不确定我是否正确理解了你的问题,但如果你想将AddMonth
方法作为参数传递,而不指定接收者对象,你可以构造一个lambda:
GetTotal(id, lastDate, (dt, num) => dt.AddMonth(num))
调用“泛化”函数。
您需要将该函数声明为:
IEnumerable<TotalType> GetTotal(string id, DateTime lastTotalDate,
Func<DateTime, int, DateTime> adder)
答案 1 :(得分:2)
var byMonths = GetTotal(123, yourDate, (d, i) => d.AddMonths(i));
var byDays = GetTotal(456, anotherDate, (d, i) => d.AddDays(i));
// ...
IEnumerable<TotalType> GetTotal(
string id, DateTime lastTotalDate, Func<DateTime, int, DateTime> adder)
{
for (int i = 0; adder(lastTotalDate, i + 1) <= DateTime.Now; i++)
{
var temp = adder(lastTotalDate, i);
var totalStartDate = new DateTime(temp.Year, temp.Month, 1);
var totalEndDate = adder(totalStartDate, 1);
var total = this.GetTotal(id, totalStartDate, totalEndDate);
var interval = new TimeInterval(totalStartDate, totalEndDate);
yield return new TotalType(id, total, interval);
}
}
答案 2 :(得分:0)
你想要做的是“Currying”。我有一个模式,我在vb.net中用于此目的;我不确定它是最好的模式,但它应该适应C#而不会有太多麻烦。请注意,虽然使用lambda表达式会限制您使用编辑和继续的能力,但使用咖喱工厂不会造成此类限制。
以下是我的问题的链接:What is the best pattern to curry delegate parameters (using .NET 2.0 or later)?
这应该很好地转化为C#;任何时候你看到括号以“(Of”,用尖括号替换它们;“ByRef Foo As Bar”和“Dim Foo As Bar”都成为“Bar Foo”。