4

適度に複雑な再試行および試行/キャッチ ロジック内で「ファイルの書き込み」操作を行うコードのチャンクがあります。これは正常に機能しています。おおよそ次のようになります。

while (...) {
try {
    FilePut(source, destination)
    }
catch () {
   //Check exception type, possibly re-throw, possibly return, possibly increment
   //counters being checked by while loop
   }
}

このロジックの詳細は問題ではありません。しかし、この同じ種類のロジック内で実行する必要がある他の操作がいくつかあることに気付きました。このロジックをコピーしてアプリケーションに貼り付けることは避けたいと考えています。関数に移動して、その関数を再利用したいと思います。その関数は、呼び出される操作への何らかの参照を取得する必要があり、try ロジックがその操作 (ファイルの書き込み、ファイルの取得など) を実行します。

これはデリゲートにとって最適な場所のように思えますが、問題は、これらの操作のそれぞれに異なる署名があるため、上記のロジックを記述して「任意の」操作を呼び出す方法がわからないことです。

C#でこれを行う良い方法はありますか?

4

2 に答える 2

5

さまざまな署名をすべて非表示にするには、Actionデリゲートが必要です。このようなもの:

public void DoAction(Action action)
{
    // Make the boilerplate code whatever you need it to be. 
    // I've just used a try catch for simplicity.
    try
    {
        // Call the action at the appropriate time.
        action();
    }
    catch
    {
        // Handle any exceptions as you wish.
    }
}

次に、さまざまなシグネチャを持つアクションを処理できるようにするために、さまざまな型のジェネリックAction<T>デリゲートと必要なすべての引数を取るいくつかのオーバーロードを定義できます。これらのオーバーロードは、ジェネリック アクションとその引数をプレーンに「カリー化」しますAction

public void DoAction<T>(Action<T> action, T arg1)
{
    DoAction(() => action(arg1));
}

public void DoAction<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2)
{
    DoAction(() => action(arg1, arg2));
}

public void DoAction<T1, T2, T3>(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3)
{
    DoAction(() => action(arg1, arg2, arg3));
}

// etc...

使用するには:

public void SomeOtherMethod()
{
    DoAction(MethodThatTakesTwoInts, 42, 23);
    DoAction(MethodThatTakesAString, "Don't Panic!");
}

また、それらに慣れていない場合は、関連するFuncデリゲートのファミリーも参照してください。

于 2012-07-23T20:02:15.050 に答える
0

再帰を使用できます:

protected void TryNTimes(int numberOfTries, Action action)
{
    try
    {
        if (numberOfTries == 0) return;
        action();
    }
    catch (Exception)
    {
        TryNTimes(numberOfTries - 1, action);
    }
}

そして、次のように使用します。

TryNTimes(10, () => Foo());
于 2012-07-23T20:12:36.313 に答える