C# 试着抓住坏形式?

C# 试着抓住坏形式?,c#,asp.net,exception-handling,C#,Asp.net,Exception Handling,我想我大概知道这个问题的答案,但做事总是有很多方法(其中一些方法显然是错误的:) 我有一个小的递归函数来查找员工经理的id。这是在导入脚本中使用的,可能是人员直接经理已经离开(被禁用),所以我们需要找到员工(经理)经理(等等),以便我们可以为他们分配内容。如果不明显,EmployeesToDisable是在此导入中标记为禁用的员工的通用列表 我想我真正想问的是:在这种情况下,捕获异常所带来的开销是不是太大了。我应该以不同的方式来做。 这确实很好,但感觉这是一种糟糕的形式 因此,我认为: priv

我想我大概知道这个问题的答案,但做事总是有很多方法(其中一些方法显然是错误的:)

我有一个小的递归函数来查找员工经理的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;
     }
    }

撇开递归不谈,您也许应该只使用
SingleOrDefault
并测试null。实际上,您可能不需要完整的employee对象——您只需返回id(在整个过程中)就足够了


实际上,我对原始表单最大的担忧是它不是特定于异常类型的;它可能是“线程中止”、“僵尸连接”、“死锁”等。

您可以使用FirstOrDefault()而不是Single来处理返回的空值。

除了其他答案

Try/Catch是非常昂贵的操作,您的简单if语句在性能方面比预期Catch和遵循逻辑更快


Try/Catch不应该是业务逻辑的一部分,相反,它们应该只是错误处理的一部分。

正如其他人所指出的,永远不要这样做。这是“最糟糕的做法”。例外情况是告诉您程序中有一个逻辑错误。通过捕获异常并继续,可以隐藏逻辑错误

只有当您肯定地知道序列中只有一个元素时,才使用Single。如果列表中可能有其他数量的元素,则使用First、FirstOrDefault、SingleOrDefault或编写自己的序列运算符;这不难做到

不使用这种最坏做法的主要原因是:

1) 正如我所说,它隐藏着一只虫子;这些异常永远不应该被捕获,因为它们永远不应该被抛出到工作程序中。异常的存在是为了帮助您调试程序,而不是控制程序流

2) 像这样使用异常作为控制流会使调试程序变得困难。调试器通常被配置为在任何异常时停止,无论它是否被处理。许多“预期”的例外情况使这一点更加困难。不应期待例外,它们应该是例外;这就是为什么它们被称为“例外”


3) catch捕获所有内容,包括可能指示应向用户报告的致命错误的内容。

感谢您的回复。。只是想知道使用==或.Equals(..@nat-readability,主要是.IMO)之间的区别(如果在本例中有)是什么,
=
更直观。在一般情况下,您还需要考虑“第一个参数是否为null”使用
.Equals
时,这不适用于
Guid
,因为它是一个
结构
“非常昂贵”是相对的……与构建LINQ查询、检查本地标识管理器、将查询组合到TSQL、通过连接执行TSQL、DB服务器检查查询缓存、解析TSQL、执行查询、处理TDS响应和从TDS执行投影的成本相比,我想我们可以这样说“异常处理(或缺少)的成本完全为零”。不过,您关于业务逻辑的观点是正确的。在本例中,他无论如何都要执行TSQL,我不是将Try/Catch与TSQL进行比较,而是将其与“IF”条件进行比较,后者可以简化以便于检查结果
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);
}