Я хочу предложить ответ, который более точно соответствует сценарию, описанному в ОП. Ключ в использовании 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
универсальный тип.