C# Action and Func parameter overloads

Seb Nilsson picture Seb Nilsson · Aug 18, 2010 · Viewed 11.4k times · Source

I need a method that takes an Action (or a Func), but the Action has a mixed number of parameters. What is the most straight forward and compact way to implement these overloads:

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) { ... } // ???

The content of the methods are exactly the same, except for the execution of the action and its parameters.

If possible, don't use any C# 4.0-specific features to solve this.

Answer

Johannes Rudolph picture Johannes Rudolph · Aug 18, 2010

The content of the methods are exactly the same, except for the execution of the action and its parameters.

That screams for using a higher order function, but since you already parameterized all the bits that are changing (execution of the action and its parameters) you're already there. Sorry, looks like you'll have to implement these overloads manually.

Just chaining through using nulls won't work since the delegates passed don't match. What you could do is wrap the passed action/func inside a lambda to peel off additional arguments:

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();
}