首页 > 解决方案 > 如何包装 FuncC# 中参数的数量和类型未知?

问题描述

假设我有这个类:

public class Function {
    public int argc;        //number of arguments of the function
    public float[] argv;
    public Func<float> f;   //attribute to store a function (e.g. Sin(x) or Pow(a, b))
}

我想创建包含Function不同函数的实例,例如Sin(x)or Pow(a, b),但我不知道如何将现有函数(带有任意数量的参数)绑定到Func. 显然,它的声明并不总是Func<float>but Func<float, float>,Func<float, float, float>等。

我一直在寻找Func, delegateAction但仍然没有弄清楚如何拥有这个“函数胶囊”,它可以保存和执行具有不同数量参数的函数。为简单起见,我认为唯一的输入和输出类型是float.

我正在考虑使用类似的东西,Func<List<float>>但我想知道是否有更好的选择。

标签: c#delegatesfunc

解决方案


我想提出一个更准确地符合 OP 描述的场景的答案。关键在于使用Delegate.DynamicInvoke它可以让您将无限数量的参数传递给委托。

public class Function<TReturn> {
    private readonly object[] _argv;

    private readonly Delegate _func;

    public Function(Delegate func, params object[] args) {
        _func = func;
        _argv = args;
    }

    public TReturn Run() {
        object v = _func.DynamicInvoke(_argv);
        return (TReturn)v;
    }
}

它的用法使您可以动态决定要传递的参数数量:

var s = new Function<double>((Func<double, double>)(x => Math.Sin(x)), 1 );
Console.WriteLine(s.Run()); // prints 0.8414709848078965

var p = new Function<double>((Func<double, double, double>)((a, b) => Math.Pow(a, b)), 2, 3);
Console.WriteLine(p.Run()); // prints 8

var d = new Function<string>((Func<string, double, string>)((a, b) => a + b.ToString()), "hello, ", 42);
Console.WriteLine(p.Run()); // prints "hello, 42"

请注意,类型检查仅在调用时在运行时执行,Function.Run()而不是在构造Function对象时执行,因为它具有动态特性。如果您确定所有传递的参数将始终属于同一类型,则可以通过添加TArg泛型类型来静态强制执行。


推荐阅读