C#错误处理catch块

时间:2013-02-06 10:40:07

标签: c#

为什么大部分时间都建议我们不应该捕获像“异常”这样的错误,而应该捕获我们期望作为开发人员的错误。 在捕获一般性错误方面是否有性能损失,还是从最佳实践的角度推荐?

  try
  {
        // Do something
  }
  catch(Exception e)
  {
        //Log error
  }

6 个答案:

答案 0 :(得分:8)

最佳做法是首先捕获特定的异常,然后转到更通用的异常。

Exception Handling (C# Programming Guide)

  

可以链接具有不同异常过滤器的多个catch块   一起。捕获块在您的上下从上到下进行评估   代码,但每个异常只执行一个catch块   抛出。第一个catch块,指定确切的类型或基数   抛出异常的类被执行。如果没有catch块指定   匹配的异常过滤器,没有过滤器的catch块   如果声明中存在一个,则被选中。 重要的是   位置捕获具有最具体的块(即最多   派生的)异常类型首先。

对于你的问题:

  

为什么大部分时间都建议不要陷入错误   “例外”但陷阱错误,我们期望作为开发人员。

一个例子是抓住NullReferenceException。从来没有一个更好的做法来捕获NullReferenceException,而应该始终在使用其实例成员之前检查对象是否为null。例如,在字符串的情况下。

string str = null;
try
{
   Console.WriteLine(str.Length)
}
catch(NullReferenceException ne)
{
    //exception handling. 
}

而是应该进行检查以检查null。

if(str != null)
   Console.WriteLine(str.Length);

修改

我认为我的问题是错误的,如果你问的是哪个例外应该被捕获,哪个不应该被IMO捕获,那些可以处理的异常应该被捕获并且休息应该保留在库中以便它们可以冒泡直至上层,进行适当的处​​理。一个例子是违反主键约束。如果应用程序正在从用户那里获取输入(包括主键)并且该日期正被插入到数据库中,则可以捕获该异常并向用户显示消息“Record already exists”然后让用户输入一些不同的价值。

但是,如果异常与外键约束相关(例如,下拉列表中的某些值被视为无效外键),则该异常应该冒泡,并且通用异常处理程序应将其记录在适当的位置。

例如,在ASP.Net应用程序中,可以在Application_Error事件中记录这些异常,并且可以向用户显示常规错误页面。

编辑2: 对于OP的评论:

  

如果处于低水平,那么将会出现性能下降   尽管知道错误是否存在,但仍会收到一般错误   的SQLException

即使存在性能差异,也应该可以忽略不计。但是抓住特定的异常,如果你知道异常是SqlException那么就抓住了。

答案 1 :(得分:4)

你应该只捕捉你可以处理的异常。 Exception过于通用,所以大多数时候你不能说你可以处理它。这有点好笑,但你应该只抓住你的例外情况:)

有些情况下你需要抓住Exception但很少见,你应该在大多数时候避免它。通常它表示一些设计问题。

答案 2 :(得分:2)

检查Eric Lippert's blog(Vexing例外)关于处理异常的最佳方法。

•不要抓住致命异常;无论如何你无能为力,并试图让它变得更糟。

•修复代码,使其永远不会触发骨头异常 - 生产代码中永远不会发生“索引超出范围”异常。

•尽可能避免因异常情况引起的那些烦恼方法的“尝试”版本而烦恼。如果您无法避免使用烦人的方法,请抓住烦恼的例外

•始终处理表示意外外生条件的异常;通常,预测每一种可能的失败都是不值得或不实际的。只需尝试操作并准备好处理异常。

答案 3 :(得分:1)

使用异常处理比实际需要更多的事实上是一种懒惰的编程方式。假设您有DataTable并且想要访问第一行。

public DataRow AccessFirstRow(DataTable dt)
{
  try
  {
    return dt.Rows[0];
  }
  catch (Exception e)
  {
    //There isn't a first row or dt is null
  }
}

而不是

public DataRow AccessFirstRow(DataTable dt)
{
  if(dt != null)
   if(dt.Rows.Count > 0)
     return dt.Rows[0];
  //If we can't access dt, then don't
  return null;
}

我的经验法则是:

  

例外情况只能用于特殊情况。

如果您决定处理它们,如上所述处理您可能遇到的特定异常,而不是通用异常。

答案 4 :(得分:1)

这是最好的做法。我们的想法是,您应该快速处理已知的异常,同时在程序中有更高级的异常,因为意外异常可能是由一些更大的主要/基本错误引起的。

答案 5 :(得分:1)

抓住您打算处理的异常。您通常希望在这样的上下文(方法)中处理特定异常,其中您有足够的信息来处理报告的错误(例如,访问用于清理的对象)。

如果try块中的代码抛出不同类型的异常,您可能希望在同一方法中处理一些异常并重新抛出其他异常,以便在调用方法中处理它们(就像在上下文中一样)处理这些例外的资源)。