传递lambda作为参数

时间:2014-01-25 15:42:29

标签: c#

我有两种方法,唯一的区别是一个lambda谓词:

public static double LowerQuartile(this IOrderedEnumerable<double> list)
{
    var median = list.Median();
    var elements = list.Where(x => x < median).ToList();
    if (!list.Contains(median))
        elements.Add(median);

    return elements.OrderBy(x => x).Median();
}

public static double UpperQuartile(this IOrderedEnumerable<double> list)
{
    var median = list.Median();
    var elements = list.Where(x => x > median).ToList();
    if (!list.Contains(median))
        elements.Add(median);

    return elements.OrderBy(x => x).Median();
}

所以我想加入它们并传递一个lambda作为参数。我试过这样的事情:

public static double CalculateQuartile(IOrderedEnumerable<double> list, Expression<Func<IOrderedEnumerable<double>,bool>> predicate)
{
    var median = list.Median();
    var elements = list.Where(predicate).ToList();
    if (!list.Contains(median))
        elements.Add(median);

    return elements.OrderBy(x => x).Median();
}

但它不起作用。我怎么能这样做?

2 个答案:

答案 0 :(得分:3)

可能是这样的

public static double Quartile(this IOrderedEnumerable<double> list,
                              Func<double,double,bool> predicate)
{
    var median = list.Median();
    var elements = list.Where(x=>predicate(x,median)).ToList();
    if (!list.Contains(median))
        elements.Add(median);

    return elements.OrderBy(x => x).Median();
}

您可以使用

var val = list.Quartile((x, y) => x > y);

答案 1 :(得分:2)

lambdas x => x < medianx => x > median都属于Func<double, bool>类型。正如您将median作为另一个变量,你必须接受它作为参数,所以最终会得到Func<double, double, bool>

public static double CalculateQuartile(this IOrderedEnumerable<double> list,
        Func<double, double, bool> predicate)
{ … }

可以将其作为表达式执行,并在运行时粘贴到median的引用中,但我建议不要这样做。

相反,我建议你以某种方式解决这个问题,你的函数用户不需要为它指定正确的lambda。毕竟,你只有两个案例:上四分位数和下四分位数。所以你可能只想让一个布尔标志作为一个参数,它允许你选择较低的上四分位数:

public static double CalculateQuartile(this IOrderedEnumerable<double> list,
        bool calculateUpperQuartile = false)
{
    var median = list.Median();
    var predicate = calculateUpperQuartile ? (x => x > median) : (x => x < median);
    var elements = list.Where(predicate).ToList();
    if (!list.Contains(median))
        elements.Add(median);

    return elements.OrderBy(x => x).Median();
}

为了让用户更容易使用它,我仍然会提供CalculateUpperQuartileCalculateLowerQuartile功能 - 但是当然,你可以在内部使用单个实现来处理它们。