C # Action and Func parameter overloads

I need a method that takes Action (or Func), but Action has a mixed amount of parameters. What is the most direct 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 is exactly the same, except for the execution of the action and its parameters.

If possible, do not use any C # 4.0 features to solve this problem.

+7
c # parameters method-overloading func action
source share
2 answers

The content of the methods is exactly the same, with the exception of the execution of the action and its parameters.

It screams to use a higher order function , but since you already parameterize all the bits that change (the execution of the action and its parameters) you are already there. Sorry, it seems you will have to do these overloads manually.

A simple join using zeros will not work, as delegates passed do not match. What you could do is wrap the passed action / func inside lambda to disable extra 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(); } 
+8
source share

This is actually a better approach (bearing in mind that Johannes indicates that you could also use a higher order function), since it is most convenient for inputting types (delegates will be automatically matched with the correct number and types of arguments) and does not require any annoying DynamicInvoke calls.

However, the latter definition of the method is problematic. An Action , by its very nature, does not accept any parameters, so it will not play well with the params object[] argument. If you want a final overload that takes a variable number of arguments, I would go with DynamicInvoke in the end, just for this method call:

 public void Execute(Delegate action, params object[] parameters) { DoStuff(); action.DynamicInvoke(parameters); DoMoreStuff(); } 

But to expand on what Johannes was talking about, I think he basically got something like this:

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

And so on - in other words, what you have already done, but in a general context, so that the code is reused elsewhere.

+5
source share

All Articles