2010-10-20 82 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」。