1

現在書いている C# の一部では、同じシグネチャを持つ複数のメソッドを同じ方法で処理する必要があります。また、将来的にはこれらの方法がさらに増える可能性があります。同じ種類のロジックを何度も繰り返す代わりに、次のことを考えました。

private delegate bool cleanStep(BuildData bd, out String strFailure);

List<cleanStep> steps = new List<cleanStep>();
steps.Add(WriteReadme);
steps.Add(DeleteFiles);
steps.Add(TFSHelper.DeleteLabel);
steps.Add(TFSHelper.DeleteBuild);

List<cleanStep>.Enumerator enumerator = steps.GetEnumerator();
bool result = true;
while (result && enumerator.MoveNext())
{
   result = enumerator.Current.Invoke(build, out strFailure);
   if (!result)
   {
      logger.Write(LogTypes.Error, strFailure);
   }
}

これにはいくつかの優れた機能があると思いますが、少し設計しすぎて難読化されているようにも感じます。

これを行うためのより良い方法に感謝できますか?

ところで:

  • トランザクションである必要はありません。
  • strFailure は例外を非表示にせず、必要に応じて完全にラップします

ありがとう。

4

4 に答える 4

9

foreach ループを使用して中断しないのはなぜですか? (慣習のためにここに名前を変更cleanStepCleanStepました - 同じことをお勧めします。)

foreach(CleanStep step in steps)
{
    string failureText;
    if (!step(build, out failureText))
    {
        logger.Write(LogTypes.Error, strFailure);
        break;
    }
}

これは、現在のコードが自動的に呼び出し、実装IEnumerator<T>しない場所の契約にも従うことに注意してください。この場合は問題になりませんが、反復子ブロックでは、ブロックの実行に破棄が使用されます。foreachDisposeIEnumerator<T>IDisposablefinally

于 2008-11-10T13:47:55.357 に答える
2

あなたのソリューションは単純明快で理解しやすいものです。別の方法で行う理由がわかりません:)

私がお勧めする唯一のことは、イテレータを foreach ループに置き換えて、エラーで中断することです。

于 2008-11-10T13:48:15.247 に答える
0

再難読化-foreachブレークを使用すると、より明確になる可能性があります(さらにDispose()、列挙子になりますが、これは行っていません)。

実際には、「params cleanStep[] ターゲット」が役立つ場合があります。

static bool RunTargets(params cleanStep[] targets)
{
    // detail as per Jon's post
}

次に、次のように呼び出すことができます。

bool foo = RunTargets(WriteReadme, DeleteFiles,
              TFSHelper.DeleteLabel, TFSHelper.DeleteBuild);
于 2008-11-10T13:49:38.690 に答える
0

文字列の代わりに Exception オブジェクトを返します。例外にはグローバル ポリシーがあることが多いため、いくつかの例外拡張機能を記述します。これで次のようになります。

static Exception Run( this IEnumerable<Step> steps) {
   return 
       steps
       .FirstOrDefault( (step) => step( build ) != null )
       .LogIfFailure();  //or .ThrowIfFailure()
}

拡張機能:

public static class ExceptionExtensions {
    private static logger = new Logger();

    public static Exception LogIfFailure( this Exception e ) {
        if( e != null )
            logger.Write( e.Message );
        return e;
    }
    public static Exception ShowDialogIfFailure( this Exception e ) {
        if( e != null )
            MessageBox.Show( e.Message );
        return e;
    }
    public static void ThrowIfFailure( this Exception e ) {
        if( e != null )
            Throw( e );
    }
}
于 2008-11-10T14:35:25.477 に答える