我需要一个采用Action(或Func)的方法,但Action有一个混合数量的参数。实现这些重载的最直接和最紧凑的方法是什么:
public void Execute<T>(Action<T> action, T param) {
// TODO: Implement something like:
// Execute(action, param, null);
}
public void Execute<T1,T2>(Action<T1,T2> action, T1 param1, T2 param2) {
// TODO: Implement something like:
// Execute(action, param1, param2, null);
}
public void Execute<T1,T2,T3>(Action<T1,T2,T3> action, T1 param1, T2 param2, T3 param3) {
DoStuff();
action(param1, param2, param3)
DoMoreStuff();
}
// OR any other type of higher order function-solution
public void Execute(Action action, params object[] parameters) { ... } // ???
除了执行动作及其参数外,方法的内容完全相同。
如果可能,请不要使用任何特定于C#4.0的功能来解决此问题。
答案 0 :(得分:8)
方法的内容完全正确 同样的,除了执行 行动及其参数。
对使用higher order function感到尖叫,但由于你已经参数化了所有正在改变的位(执行动作及其参数),你已经存在了。抱歉,看起来你必须手动实现这些重载。
由于传递的委托不匹配,因此只使用空值链接将无效。你可以做的是将传递的action / func包装在lambda中以剥离其他参数:
public void Execute(Action<T> action, T param) {
Execute( (a, _) => action(a) , param, null);
}
public void Execute(Action<T1, T2> action, T1 param1, T2 param2) {
Execute( (a, b, _) => action(a, b) , param1, param2, null);
}
public void Execute(Action<T1, T2, T3> action, T1 param1, T2 param2, T3 param3) {
DoStuff();
action(param1, param2, param3)
DoMoreStuff();
}
答案 1 :(得分:5)
这实际上是最好的方法(记住Johannes的观点,你也可以使用更高阶的函数),因为它是最类型友好的(委托将自动匹配正确的参数数量和类型)并且不需要任何麻烦的DynamicInvoke
电话。
然而,您的上一个方法定义存在问题。 Action
本质上不接受任何参数,因此它不会与params object[]
参数一起使用。如果你想要一个接受可变数量参数的最终重载,那么毕竟我会选择DynamicInvoke
,只是为了这个方法调用:
public void Execute(Delegate action, params object[] parameters)
{
DoStuff();
action.DynamicInvoke(parameters);
DoMoreStuff();
}
但是为了扩展约翰内斯所说的话,我认为他基本上就是这样:
public Action<T1, T2, T3> CreateAction<T1, T2, T3>(Action action)
{
return (T1 x, T2 y, T3 z) => action();
}
public Action<T1, T2, T3> CreateAction<T1, T2, T3>(Action<T1> action, T1 arg)
{
return (T1 x, T2 y, T3 z) => action(arg);
}
依此类推 - 换句话说,就是你已经完成的事情,但是在一般情况下,代码可以在其他地方重复使用。