8

Action (または Func) を受け取るメソッドが必要ですが、Action にはさまざまな数のパラメーターがあります。これらのオーバーロードを実装する最も簡単でコンパクトな方法は次のとおりです。

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 固有の機能を使用しないでください。

4

2 に答える 2

8

アクションとそのパラメーターの実行を除いて、メソッドの内容はまったく同じです。

それは高次関数を使用することを叫びますが、変更されているすべてのビット (アクションとそのパラメーターの実行) を既にパラメーター化しているので、既にそこにいます。申し訳ありませんが、これらのオーバーロードを手動で実装する必要があるようです。

渡されたデリゲートが一致しないため、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();
}
于 2010-08-18T07:54:03.117 に答える
5

これは実際には最良のアプローチであり(高階関数も使用できるというヨハネスの指摘を念頭に置いて)、最もタイプに適しているため(デリゲートは自動的に正しい数とタイプの引数と照合されます)、面倒な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);
}

など-言い換えれば、あなたがすでに行ったことですが、コードが他の場所で再利用できるように、一般的なコンテキストで。

于 2010-08-18T09:52:50.400 に答える