C # Действие и Перегрузка параметров функции

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

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 функции для решения этой проблемы.

7
задан Ruben Bartelink 18 August 2010 в 09:42
поделиться

2 ответа

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

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

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

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
ответ дан 6 December 2019 в 19:31
поделиться

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

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

5
ответ дан 6 December 2019 в 19:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: