我有这个功能:
bool TrySomething(IEnumerable<T> items, out List<T> listOfProblemItems)
{
//...
return listOfProblemItems != null && listOfProblemItems.Count > 0;
}
现在的工作方式与您从“ TrySomething”模式(例如
TryParse
)所期望的相反:如果出了什么问题,它会返回
true
(以指示out
参数已填充信息)。这样我就可以这样称呼它:if(TrySomething(items, out problemItems))
{
//handle problems
//"but.. it returned 'true'! Why are there problems? I'm confused."
}
如果出现问题,返回
true
是不直观的,但是如果我将其更改为false
,则out
参数将充满false
上的信息,从而破坏“ TrySomething”模式。if(TrySomething(items, out problemItems) == false)
{
//handle problems
//"the 'out' parameter is used? but it returned false! I'm confused."
}
对于我来说,抛出异常不是替代选择,因为这是一项高性能的工作,并且我需要明确定义哪些项仍然失败的列表。
我可以让它返回问题列表并将其命名为
TrySomethingAndReturnAnyProblems
,但是这个名称很丑陋,调用代码必须检查返回的列表中是否为null和计数,我宁愿在函数中执行此操作,因为它总是无论如何必须要做。List<T> problems = TrySomethingAndReturnAnyProblems(items);
if(problems != null && problems.Count > 0)
{
//ugly and introduces duplicate code every time the function is used.
}
在保留“ TrySomething”模式的简洁性的同时,如何使它成为可读的,具有自文档功能的函数定义?
最佳答案
如何编写扩展方法以简单地过滤出有问题的项目呢?这样,您只能取回可以的项目,例如:
public static IEnumerable<T> ExceptProblematic(this IEnumerable<T> items)
{
foreach (var item in items)
{
if (!IsProblematic(item))
yield return item;
}
}
这样,您可以像这样使用它:
var validItems = items.ExceptProblematic();
或者,您可以编写查询以仅返回问题项,然后进行另一个查询以将其过滤掉,例如:
var problemItems = items.Where(item => IsProblematic(item));
var validItems = items.Except(problemItems);
然后相应地处理问题项:
if (problemItems.Any())
{
// handle problem items
}