在不指定委托参数的情况下调用委托

时间:2010-10-20 23:09:39

标签: c# delegates

我有两个类似的函数,我希望重构以删除重复:

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值。

建议?

3 个答案:

答案 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”。