我有以下丑陋的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语句的常用方法是为每个条件创建一个子类。
这个例子的不同之处是:
任何建议都非常受欢迎。
答案 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属性如果声明更具可读性,则会掩盖你的双重条款。
无论哪种方式都可以达到使其更具可读性的相同结果。