Вопрос

Мне нужен метод, который принимает действие (или функцию функции), но действие имеет смешанное количество параметров. Какой самый прямой и компактный способ реализации этих перегрузок:

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, чтобы решить это.

Это было полезно?

Решение

Содержание методов точно так же, за исключением выполнения действия и его параметров.

Что кричит для использования Функция высшего порядка, но так как вы уже параметризовали все биты, которые меняются (выполнение действия и его параметры), вы уже там. Извините, похоже, вам придется реализовать эти перегрузки вручную.

Просто цепи через использование нулей не будет работать, так как делегаты не совпадают. Что вы могли сделать, это Оберните пропущенное действие / функцию внутри лямбда, чтобы отслаться дополнительными аргументами:

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

Другие советы

Это на самом деле лучший подход (помному признаку того, что вы могли бы также использовали функцию более высокого порядка), так как это наиболее удобно (делегаты будут соответствовать правильному номеру и типам аргументов) и делает не требует никого нами 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);
}

И так далее - другими словами, что вы уже сделали, но в общем контексте, чтобы код был многоразовым в других местах.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top