Pass Action<.., .., T > as Parameter without a predefined number of action parameters

832 views Asked by At

I have the following code:

public doSomething(List<Int64> data, Int64 counter){
    //Do something
}    

public doSomethingNext(List<Int64> data, String Something){
    //Do something next
}    

public static void Loop<T>(Action<T> action) {
        //Do something before
        action(T);
    }
}

Is it possible to write the Loop method in such a generic way, that I can pass every method regardless of the parameters of the method. Something like this:

Loop(doSomething,....?);
Loop(doSomethingNext,...?);

@Edit 19:40 24-06-2015 More information

Sorry the 'action(T);' part generates the error that T is unknown. However I filled it in there because I do not know how to make this work.

When I use the following code it works with Linq:

//Method
public static void Loop(Action action) {
    //Do something before
    action();
    }
}

//Call
Loop(() => doSomething(data, counter));

However I am curious if it can also work without Linq? (With something like < T >)

(A side-question, is it possible to be able to access the parameters of the method in the Loop function?)

2

There are 2 answers

0
shf301 On BEST ANSWER

Use a lambda method when calling Loop to transform your method into an Action:

 Loop(t => doSomething(t, counter));

 Loop(t => doSomethingNext(t, Something));
6
xanatos On

You can have as the parameter a Delegate... like:

public static void Loop<T>(Delegate action) {
}

but then you would have to

action.DynamicInvoke(someparameters);

so use reflection to invoke it... and what parameters would you use?


Normally if the parameters are "fixed" and "chosen" by the caller, this problem is solved with partial application:

public static void Loop(Action action)
{
    action();
}

and you use it like:

Loop(() => Console.WriteLine("Hello"));

here Console.WriteLine() has one parameter, but it is fixed by the caller through the creation of another method (an anonymous method) with 0 parameters from which a delegate of type Action is created.

You don't need to remove all of the arguments from the delegate though:

public static void Loop<T>(Action<T> action)
{
    // generate some T value
    T value = GetValue<T>();

    // call action with a T parameter
    action(value);
}

and then:

Loop((int x) => Console.WriteLine("Some number: {0}", x));

In this case, Console.WriteLine() is using two parameters, of which one has been fixed ("Some number: {0}") and one remains truly variable (x).