我想我知道这个问题的答案,但总有很多方法可以做(其中一些显然是错误的:) :) ...
我有一个小的递归功能来查找员工经理的ID。这是在导入脚本中使用的,可能是直接经理人离开(被禁用)所以我们需要找到员工(经理)经理(等等),以便我们可以为他们分配东西。如果不明显,EmployeesToDisable是在此导入中标记为已禁用的员工的通用列表。
我想我真正要问的是:在这种情况下,捕获异常的开销太大了。我应该以不同的方式做这件事。 这确实很好,但感觉它是不好的形式..
我有代码:
private Guid getMyEnabledManagersID(OnlineEmployee e)
{
Employee manager;
try
{
//see if Employee e's manager is in the disabled list.
manager = (from emp in EmployeesToDisable where emp.EmployeeID.Equals(e.ManagerID) select emp).Single();
//yes they are, so need to call this again
return getMyEnabledManagersID(manager);
}
catch
{
return e.ManagerID;
}
}
答案 0 :(得分:6)
除了递归之外,您应该只使用SingleOrDefault
并测试null。实际上,你可能不需要完整的员工对象 - 你可以只返回id(整个)就足够了,即
private Guid getMyEnabledManagersID(Guid managerId)
{
var disabled = (from emp in EmployeesToDisable
where emp.EmployeeID == managerId
select (Guid?)emp.ManagerID).SingleOrDefault();
return disabled == null ? managerId : getMyEnabledManagersID(disabled.Value);
}
实际上,我对原始表单的最大关注点是它并不特定于异常的类型;它可能是“线程中止”,“僵尸连接”,“死锁”等等。
答案 1 :(得分:6)
正如其他人指出的那样从不这样做。这是“最糟糕的做法”。例外情况是告诉您您的程序中存在逻辑错误。通过捕获异常并继续,您可以隐藏逻辑错误。
只有在知道时才使用Single,积极且肯定地说,序列中只有一个元素。如果列表中可能有其他数量的元素,则使用First,FirstOrDefault,SingleOrDefault或编写自己的序列运算符;这不难做到。
不使用这种最差做法的主要原因是:
1)正如我所说,它隐藏了一个错误;这些异常应该从不被捕获,因为它们永远不会被抛入工作程序中。有例外可以帮助您调试程序,而不是控制它的流程。
2)使用异常作为这样的控制流使得调试程序变得困难。调试器通常配置为在任何异常时停止,无论是否处理。很多“预期的”例外使得更难。绝不应该例外,它们应该例外;这就是为什么他们被称为“例外”。
3)捕获捕获所有内容,包括可能表示应向用户报告的致命错误的内容。
答案 2 :(得分:1)
除了其他答案,
Try / Catch是非常昂贵的操作,简单的if语句在性能方面更快,然后期望捕获然后遵循逻辑。
Try / Catch不应该是业务逻辑的一部分,而应该只是错误处理的一部分。
答案 3 :(得分:0)
您可以使用FirstOrDefault()而不是Single并处理返回的空值。