我有这个功能:

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
}

10-07 13:50