C# 将带有两个参数的委托作为参数函数传递

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/713634/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 22:12:01  来源:igfitidea点击:

Passing a delegate with two parameters as a parameter function

c#delegates

提问by Stefano Ricciardi

I have a sequence of functions that look very similar but for a single line, like the following two (but I have many more of them):

我有一系列看起来非常相似但只有一行的函数,如下两个(但我有更多):

private static int HowManyHoursInTheFirstYear(IList<T> samples)
{
    DateTime firstDate = samples[0].Date;
    int count = 0;

    while (count < samples.Count && 
          samples[count].Date.Year == firstDate.Year)
    {
        count++;
    }

    return count;
}


private static int HowManyDaysInTheFirstMonth(IList<T> samples)
{
    DateTime firstDate = samples[0].Date;
    int count = 0;

    while (count < samples.Count && 
           samples[count].Date.Month == firstDate.Month) // <--- only change!
        count++;
    }

    return count;
}

I was thinking about using delegates to remove this repetition in code in some elegant way, that would have allowed me to invoke something like:

我正在考虑使用委托以某种优雅的方式删除代码中的这种重复,这将允许我调用以下内容:

HowManyDaysInTheFirstPeriod(
    samples,
    delegate(DateTime d1, DateTime d2) { return d1.Month == d2.Month; });

thereby declaring a delegate like the following:

从而声明一个如下所示的委托:

delegate bool DateComparer(DateTime first, DateTime second);

and where HowManyDaysInTheFirstPeriod whould be something like the following:

以及 HowManyDaysInTheFirstPeriod 应该如下所示:

private static int HowManySamplesInFirstPeriod
    IList<T> samples,
    DateComparer comparer)
{
    DateTime firstDate = samples[0].Date;
    int count = 0;

    while (count < samples.Count && comparer())
    {
        count++;
    }
}

Unfortunately, the compiler complains that comparer needs two parameters.

不幸的是,编译器抱怨 comparer 需要两个参数。

I am relatively new to C# and hit a road-block here. How would you solve this?

我对 C# 比较陌生,在这里遇到了障碍。你会如何解决这个问题?

采纳答案by John Feminella

You're almost there! The comparerdelegate parameter is just like any other function: You still need to pass the appropriate arguments to invoke it.In your case, that's going to mean this change:

您快到了!该comparer委托参数就像任何其他的功能:您仍然需要通过适当的参数来调用它。在您的情况下,这将意味着此更改:

while (count < samples.Count && comparer(samples[count].Date, firstDate))
{
    count++;
}

(Also, note that samplesshould probably be samples.Count, as I have written above.)

(另外,请注意,samples可能应该是samples.Count,正如我上面写的那样。)

回答by Jon Skeet

You need to pass the comparer the two dates in question. It's probably juts as simple as:

您需要将有问题的两个日期传递给比较器。这可能很简单:

private static int HowManySamplesInFirstPeriod
    IList<T> samples,
    DateComparer comparer)
{
    DateTime firstDate = samples[0].Date;
    int count = 0;

    while (count < samples.Count 
           && comparer(samples[count].Date, firstDate))
    {
        count++;
    }
}

Or you may want to pass them the other way round (i.e. firstDateand then samples[count].Date).

或者您可能想以相反的方式传递它们(即firstDate然后samples[count].Date)。

回答by Kent Boogaart

You need to pass the dates being compared to the delegate. So:

您需要传递与委托进行比较的日期。所以:

comparer(samples[count].Date, firstDate)

回答by jalf

You can do it a bit simpler. Simply provide the function a delegate which extracts whatever should be compared from a DateTime:

你可以做得更简单一点。只需为函数提供一个委托,该委托从 DateTime 中提取应该比较的内容:

private static int HowManySamplesInFirstPeriod<T>
    IList<T> samples,
    Func<DateTime, int> f // a function which takes a DateTime, and returns some number
{
    DateTime firstDate = samples[0].Date;
    int count = 0;

    while (count < samples && f(samples[count].Date) == f(firstDate))
    {
        count++;
    }
}

and it can then be called as such:

然后可以这样调用它:

HowManySamplesInFirstPeriod(samples, (dt) => dt.Year); // to get the year
HowManySamplesInFirstPeriod(samples, (dt) => dt.Month); // to get the month

The (dt) => dt.yearsyntax may be new to you, but it's a cleaner way of writing "an anonymous delegate which takes an object dt of some generic type, and returns dt.year". You could write an old-fashioned delegate instead, but this is nicer. :)

(dt) => dt.year语法可能是新的给你,但它写的更清洁的方式“匿名委托这需要一些通用类型的对象,DT,并返回dt.year”。你可以写一个老式的委托,但这样更好。:)

We can make it a bit more general than that though, by adding another generic type parameter:

不过,我们可以通过添加另一个泛型类型参数使其更通用:

private static int HowManySamplesInFirstPeriod<T, U>
    IList<T> samples,
    Func<DateTime, U> f // Let's generalize it a bit, since the function may return something other than int (some of the DateTime members return doubles, as I recall)

As usual though, LINQ provides a nicer still alternative:

像往常一样,LINQ 提供了一个更好的选择:

private static int HowManySamplesInFirstPeriod<T>
    IList<T> samples,
    Func<DateTime, int> f)
{
  var firstVal = f(samples.First().Date);
  return samples.Count(dt => f(dt.Date) = firstVal)
}

回答by sipwiz

I think jalf's answer needs to be modified slightly to fit the original usage:

我认为需要稍微修改 jalf 的答案以适应原始用法:

private static int HowManyHoursInTheFirstYear(IList<DateTime> samples, Func<DateTime, DateTime, bool> comparer) 
{ 
    DateTime firstDate = samples[0].Date; 
    int count = 0;
    while (count < samples.Count && comparer(samples[count], firstDate) ) {
        count++;
    } 
    return count; 
}

Call using:

调用使用:

HowManyDaysInTheFirstPeriod(samples, (d1, d2) = > { return d1.Month == d2.Month; });
HowManyDaysInTheFirstPeriod(samples, (d1, d2) = > { return d1.Year == d2.Year; });