【发布时间】:2013-11-20 12:44:32
【问题描述】:
我有这个功能:
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,但是这个名字很难看,调用代码必须检查返回的列表是否为空和计数,我' d 宁愿在函数中完成,因为无论如何它总是必须完成。
List<T> problems = TrySomethingAndReturnAnyProblems(items);
if(problems != null && problems.Count > 0)
{
//ugly and introduces duplicate code every time the function is used.
}
如何在保持“TrySomething”模式的简洁性的同时将其变成可读的、自记录的函数定义?
【问题讨论】:
-
return listOfProblemItems == null || listOfProblemItems.Count == 0;怎么样?顺便说一句,我会删除bool返回值并直接返回列表。调用者可以简单地检查一个空列表...... -
也许你不应该使用
TryX模式。TryX方法将out参数用于结果,而不是用于报告问题。你马上就打破了这种模式。 -
首先,自定义异常类型当然可以包含问题列表。其次,异常在不被抛出时并不慢。换句话说:当你的程序不工作时,它真的必须不能快速工作吗?最后但并非最不重要的一点是,异常可能并不像您想象的那么慢。您正在构建一个问题列表,然后循环访问该列表。该过程中的异常成本很可能可以忽略不计。
-
@KrisVandermotten:他正在编写一个预计会经常失败的方法,否则该方法本身将是多余的。
-
int TrySomething(IEnumerable<T> items, Action<T> problemCallback)怎么样?
标签: c# design-patterns coding-style out