2010-10-20 71 views
0

我有两个类似的功能,我希望重构,以消除重复:电话委托不指定委托的参数

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的参数值。

对此提出建议?

回答

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

我不知道如果我理解正确你的问题,但如果你想通过AddMonth方法作为参数,而不指定接收对象,你可以构造一个拉姆达:

GetTotal(id, lastDate, (dt, num) => dt.AddMonth(num)) 

调用“通用化”功能。

您需要声明功能:

IEnumerable<TotalType> GetTotal(string id, DateTime lastTotalDate, 
    Func<DateTime, int, DateTime> adder) 
0

什么你正在寻找做被称为“柯里化”。我有一个在vb.net中用于这个目的的模式;我不确定这是最好的模式,但它应该适用于C#而没有太多的麻烦。请注意,虽然使用lambda表达式会限制您使用edit-and-continue的能力,但使用咖喱工厂不会造成这种限制。

这里是我的问题的链接: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”。