我可以设置一个Func<>使用运行时变量来省略在C#中将它们作为参数传递?

时间:2009-12-24 08:06:55

标签: c# delegates runtime func

我有一个数值分析程序,为简单起见计算类似于以下算法:

y = ax^3 + bx^2 + cx + d;

我在运行时计算a,b,c,d的值,并希望将以下等价物作为Func<double, double>传递。我可以在哪里设置X的值,并获得Y.

y = 12x^3 + 13x^2 + 14x + 15; 

其中12,13,14,15是在运行时计算的数字。

我意识到这可以通过传入双数组来完成,如下所示:Func<double[], double> 但我试图避免传递常数(可能很多)。

有没有办法在运行时在func中设置这些数字?

(优选不计算func&lt;&gt;本身的a,b,c,d部分?a,b,c,d的计算是工作的80%)

E.g:

a = ...

b = ...

c = ...

Func<x, double> {
     ((const)a) * x^3 +   ((const)b) * x^2 +   ((const)c) * x + 15;
}`

对于ABCD的每次评估 - 我将评估10 x。

5 个答案:

答案 0 :(得分:11)

我不确定我是否理解你的要求,但你可以尝试这样的事情吗?

Func<double, double> CreateCalculationFunc()
{
    double a = heavy calculation;
    double b = heavy calculation;
    double c = heavy calculation;
    double d = heavy calculation;

    Func<double, double> calculation = (x) =>
    {
        // You can use the constants in here without passing them as parameters
        return x * (a * b / c - d);
    };

    return calculation;
}

在这种情况下,您只需调用CreateCalculationFunc(),这将进行一次繁重的计算,并返回可重复使用的Func<double,double>进行变量计算。

当然,这可以扩展到任何数量的预先计算的常量和多个变量。

答案 1 :(得分:2)

无法创建包含计算(Func<double,double>)方法的类,该方法具有“常量”的属性。然后设置属性并使用Calculate方法的引用作为Func<double,double>委托:

public class Calculator
{
    public double A { get; set; };
    public double B { get; set; };
    public double C { get; set; };
    public double D { get; set; };

    public double Calculate(double x)
    {
        return A*x*x*x + B*x*x + C*x + D;
    }
}

答案 2 :(得分:2)

这听起来像你想要的功能语言叫做“currying”或“部分应用”。

给定Func<a, b, c, d, x, result>,您将逐个应用这些值并减少参数集。

Func<a, b, c, d, x, result>(valueOfA)

将导致带有签名的函数

Func<b, c, d, x, result>

你可以传递。

C#中的currying / partial应用程序的相关链接:

或 - 试试F#;)

编辑:从上面的参考站点创建的短代码示例:

Boilerplate代码:

    public static Func<B, R> Partial<A, B, R>(this Func<A, B, R> f, A a) {
        return b => f(a, b);
    }

    public static Func<B, C, R> Partial<A, B, C, R>(this Func<A, B, C, R> f, A a) {
        return (b, c) => f(a, b, c);
    }

    public static Func<B, C, D, R> Partial<A, B, C, D, R>(this Func<A, B, C, D, R> f, A a) {
        return (b, c, d) => f(a, b, c, d);
    }

您的密码:

Func<double, double, double, double, double> yourCalculation = (a, b, c, x) => a*Math.Pow(x, 3) + b*Math.Pow(x, 2) + c*x;

var aDefined = yourCalculation.Partial(12);
var bDefined = aDefined.Partial(13);
var cDefined = bDefined.Partial(14);

cDefined现在是一个新的Func,它“知道”预先应用的值,并且可以随意传递。我找不到具有4个以上参数的代表的现成解决方案(即那些不适合Func&lt; ...&gt;的东西),但这也应该是可能的。

通过这种方式,您可以预先计算一次,就像今天的方式一样,但是您可以将功能范围缩小到每个消费者的最后一部分。

答案 3 :(得分:0)

有几种不同的Func&lt;&gt;重载,您可以使用一个with 5 generic parameters,第一个是KeyValuePair

Func<KeyValuePair<double,double>,double,double,double,double>

所以你传递a和b作为kvp和c,d和x作为其他参数。

答案 4 :(得分:0)

事后我真的可以这样做;

Class {
    a = ...
    b = ...

    Func Algorithm = (x) => {
        return x*a + x*b;
    }

    return Algorithm;
}

但Func&lt;&gt;只是有点困惑。和行动&lt;&gt;因为这是我第一次使用它们!谢谢你的帮助。