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 循环然后中断?(我已将其重命名cleanStep为此CleanStep处以保持常规 - 我建议您也这样做。)

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

请注意,这也遵守IEnumerator<T>您当前代码不foreach自动调用DisposeIEnumerator<T>实现的约定IDisposable。在这种情况下这不是问题,但是对于迭代器块,处置用于执行finally

于 2008-11-10T13:47:55.357 回答
2

您的解决方案既简单明了又易于理解。我看不出有什么理由用另一种方式来做:)

我唯一建议的是用 foreach 循环替换您的迭代器并在错误时中断。

于 2008-11-10T13:48:15.247 回答
0

重新混淆 -foreach使用 break 可能会更清晰(加上它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

我会返回一个异常对象而不是一个字符串。由于异常通常具有全局策略,因此我会编写一些异常扩展。现在你得到:

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 回答