C# 需要以相同方式处理的多个方法

C# 需要以相同方式处理的多个方法,c#,delegates,C#,Delegates,在我正在编写的一段C代码中,我需要以相同的方式处理几个具有相同签名的方法。将来可能还会有更多的这种方法。我没有反复重复同样的逻辑,而是想到了以下几点: private delegate bool cleanStep(BuildData bd, out String strFailure); List<cleanStep> steps = new List<cleanStep>(); steps.Add(WriteReadme); steps.Add(DeleteFile

在我正在编写的一段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不会隐藏异常,而是将它们包装起来 必要时完全
谢谢

为什么不使用foreach循环并中断呢?出于惯例,我将cleanStep重命名为cleanStep-我建议您也这样做

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

请注意,这也遵守IEnumerator的约定,您当前的代码不会这样做—foreach自动调用Dispose,IEnumerator实现IDisposable。在这种情况下这不是问题,但是对于迭代器块,。

为什么不使用foreach循环并中断呢?出于惯例,我将cleanStep重命名为cleanStep-我建议您也这样做

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

请注意,这也遵守IEnumerator的约定,您当前的代码不会这样做—foreach自动调用Dispose,IEnumerator实现IDisposable。在这种情况下,这不是问题,但使用迭代器块,。

您的解决方案既简单又易于理解。我看不出有任何理由用另一种方式:


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

您的解决方案既简单又易于理解。我看不出有任何理由用另一种方式:

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

重新模糊-使用break的foreach可能更清晰,而且它将处理枚举数,而您没有这样做

实际上,params cleanStep[]目标可能有助于:

static bool RunTargets(params cleanStep[] targets)
{
    // detail as per Jon's post
}
然后你可以打电话:

bool foo = RunTargets(WriteReadme, DeleteFiles,
              TFSHelper.DeleteLabel, TFSHelper.DeleteBuild);
重新模糊-well foreach with break可能更清晰,而且它将处理枚举数,而您没有这样做

实际上,params cleanStep[]目标可能有助于:

static bool RunTargets(params cleanStep[] targets)
{
    // detail as per Jon's post
}
然后你可以打电话:

bool foo = RunTargets(WriteReadme, DeleteFiles,
              TFSHelper.DeleteLabel, TFSHelper.DeleteBuild);

我将返回一个异常对象而不是字符串。由于异常通常有一个全局策略,所以我将编写一些异常扩展。现在您可以:

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

我将返回一个异常对象而不是字符串。由于异常通常有一个全局策略,所以我将编写一些异常扩展。现在您可以:

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

看起来已经好多了。还学习了有关枚举数处理的新知识。谢谢我对break语句有点反感,但在这里它确实是有意义的。这看起来已经更好了。还学习了有关枚举数处理的新知识。谢谢我对break语句有点反感,但它在这里确实有意义。谢谢,这实际上是我喜欢的特性之一。你可以重构这个函数,但也可以创建列表。谢谢,这实际上是我喜欢的特性之一。你可以重构这个函数,也可以创建列表。谢谢。我喜欢干净的沙发,但当一步失败时它不会停止。我知道我说过它不需要是事务性的,但是当一个步骤失败时,我们甚至不想尝试其余的步骤。谢谢。我喜欢干净的沙发,但当一步失败时它不会停止。我知道我说过它不需要是事务性的,但是当一个步骤失败时,我们甚至不希望它尝试其余的步骤。