我怎样才能清理这个丑陋的if语句?

时间:2009-06-28 07:00:30

标签: c# .net

我有以下丑陋的if语句,它是从IOC容器中提取的类的一部分:

protected virtual void ExecuteSourceControlGet(IBuildMetaData buildMetaData, IPackageTree componentTree)
{
    if ((buildMetaData.RepositoryElementList != null) && (buildMetaData.RepositoryElementList.Count > 0))
    {
        componentTree.DeleteWorkingDirectory();

        foreach (var repositoryElement in buildMetaData.RepositoryElementList)
        {
            repositoryElement.PrepareRepository(componentTree, get).Export();
        }

    }

    if((buildMetaData.ExportList != null) && (buildMetaData.ExportList.Count > 0))
    {
        var initialise = true;

        foreach (var sourceControl in buildMetaData.ExportList)
        {
            log.InfoFormat("\nHorn is fetching {0}.\n\n".ToUpper(), sourceControl.Url);

            get.From(sourceControl).ExportTo(componentTree, sourceControl.ExportPath, initialise);

            initialise = false;
        }

    }

    log.InfoFormat("\nHorn is fetching {0}.\n\n".ToUpper(), buildMetaData.SourceControl.Url);

    get.From(buildMetaData.SourceControl).ExportTo(componentTree);
}

我消除if语句的常用方法是为每个条件创建一个子类。

这个例子的不同之处是:

  1. 具有此方法的类将从IOC容器中提取。
  2. 我可能希望2个if语句之间的逻辑运行或根本不运行。
  3. 任何建议都非常受欢迎。

4 个答案:

答案 0 :(得分:14)

我不确定你为什么要删除if语句 - 并且使用继承它似乎超过顶部。您可能希望为重复的集合代码创建扩展方法:

public static bool HasElements<T>(this ICollection<T> collection)
{
    return collection != null && collection.Count != 0;
}

这使您可以将条件更改为:

if (buildMetaData.RepositoryElementList.HasElements())

if (buildMetaData.ExportList.HasElements())

这是一个稍微简单的IMO。如果最终存在更多逻辑,您可能还想将两个块分成不同的方法。除此之外,我不担心。

哦,还有另一种扩展方法,如果你需要关心你是否有元素,那将无济于事,但如果你只想做一个无效的foreach会有所帮助:

public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> source)
{
    return source ?? Enumerable.Empty<T>();
}

(并不是说使用内联的空合并运算符非常节省,不可否认......)

答案 1 :(得分:4)

如何使用两个提取方法,并将if反转为守卫:

protected virtual void ExecuteSourceControlGet(IBuildMetaData buildMetaData, IPackageTree componentTree)
{
   ExecuteRepositoryElementList(buildMetaData.RepositoryElementList, componentTree);

   ExecuteExportList(buildMetaData.ExportList, componentTree);

   log.InfoFormat("\nHorn is fetching {0}.\n\n".ToUpper(), buildMetaData.SourceControl.Url);

   get.From(buildMetaData.SourceControl).ExportTo(componentTree);
}

private void ExecuteRepositoryElementList(RepositoryElementList repositoryElements, IPackageTree componentTree)
{
   // Guard: No elements
   if (repositoryElements == null || repositoryElements.Count == 0) return;

   componentTree.DeleteWorkingDirectory();

   foreach (var repositoryElement in repositoryElements)
   {
      repositoryElement.PrepareRepository(componentTree, get).Export();
   }
}

private void ExecuteExportList(ExportList exportList, IPackageTree componentTree)
{
   // Guard: No elements
   if(exportList == null || exportList.Count == 0) return;

   var initialise = true;

   foreach (var sourceControl in exportList)
   {
      log.InfoFormat("\nHorn is fetching {0}.\n\n".ToUpper(), sourceControl.Url);

      get.From(sourceControl).ExportTo(componentTree, sourceControl.ExportPath, initialise);

      initialise = false;
   }
}

BTW:必须使用正确类型的 IBuildMetaData.RepositoryElementList IBuildMetaData.ExportList 修复这两种方法。

答案 2 :(得分:0)

protected virtual void ExecuteSourceControlGet
    (IBuildMetaData metaData, IPackageTree tree)
{
    if (metaData.RepositoryElementList.HasElements())
    {
        tree.DeleteWorkingDirectory();

        foreach (var element in metaData.RepositoryElementList)
             element.PrepareRepository(tree, get).Export();    
    }

    if(metaData.ExportList.HasElements())
    {
        var init = true;

        foreach (var sourceControl in metaData.ExportList)
        {
            log.InfoFormat
              ("\nHorn is fetching {0}.\n\n".ToUpper(), sourceControl.Url);

            get.From(sourceControl)
              .ExportTo(tree, sourceControl.ExportPath, init);

            init = false;
        }

    }

    log.InfoFormat
       ("\nHorn is fetching {0}.\n\n".ToUpper(), 
           metaData.SourceControl.Url);

    get.From(metaData.SourceControl)
       .ExportTo(tree);
}

//Credits goes to Jon Skeet...
public static class CollectionExtensions
{
    public static bool HasElements<T>(this ICollection<T> collection)
    {
        return collection != null && collection.Count != 0;
    }
}

答案 3 :(得分:0)

我要么像John建议的那样创建一个扩展方法,要么(如果这在你的类的其余部分的上下文中有意义的话)重构它并使buildMetaData成为类的一个成员并且有一个带有get的两个私有bool属性如果声明更具可读性,则会掩盖你的双重条款。

无论哪种方式都可以达到使其更具可读性的相同结果。