C#中各种try-catch有什么区别?

时间:2011-07-17 10:10:49

标签: c# try-catch

  

可能重复:
  the difference between try/catch/throw and try/catch(e)/throw e

请原谅我的愚蠢,有谁知道他们之间的区别?

 try
 {
      return 1 / 0;
 }
 catch (Exception)
 {
      throw;
 }

 try
 {
      return 1 / 0;
 }
 catch
 {
      throw;
 }

 try
 {
      return 1 / 0;
 }
 catch (Exception e)
 {
      throw(e);
 }

6 个答案:

答案 0 :(得分:4)

  1. 将仅捕获并重新抛出从Exception派生的异常。
  2. 将捕获并重新抛出任何异常。 (编辑:自CLRv2以来,所有异常都来自Exception,因此这与1相同。请参阅下面的Eric Lippert的评论。
  3. 将捕获从Exception派生的任何异常并再次抛出它,从而重置异常的堆栈跟踪。

答案 1 :(得分:2)

不带参数的catch子句可以捕获任何类型的异常。这有时被称为“一般”捕获条款。您可能永远不会在生产应用程序中使用它,但我认为它有时可能对调试很有用。它看起来像这样:

catch
{
}

catch子句还可以指定要捕获的特定异常类。您应该始终在您的应用程序中执行此操作,因为您应该只捕获您知道如何处理的异常。例如,您可能想要捕获DivideByZeroException;你这样做是这样的:

catch (DivideByZeroException)
{
}

当然,这会产生副作用,即您无法在catch块内引用异常类本身,因为您尚未将其分配给变量。如果需要在捕获的异常类的实例上调用属性或方法,则需要在catch语句中包含命名变量。这可能是你过去常常看到的,它看起来像这样:

catch (DivideByZeroException ex)
{
    // do something with ex here
}

然后有两种方法来编写throw()语句,重要您选择哪一种:

  1. 第一个看起来像这样:

    throw;
    

    它的编写没有任何参数,目的是重新抛出捕获的异常,同时保留堆栈跟踪和尽可能多的有关原始异常的信息。
    (仍然存在一些边缘情况,这会导致您丢失堆栈跟踪,但通常情况下, 优先于下面的替代方案。)

  2. 第二个选项将异常类的实例作为参数传递,如下所示:

    throw(ex);
    

    或者这个:

    throw ex;
    

    这个重新抛出指定的异常,但如上所述,它的缺点是丢失一些堆栈跟踪信息,告诉你什么方法负责抛出异常。除了抛出您在同一方法中创建的 new 异常对象之外,您很少使用它。

    例如,如果您想要捕获一个低级异常并在新异常对象中 wrap 以供更高级别的函数使用,那么您将使用此表单。

答案 2 :(得分:1)

前两个是等效的。

通常应避免使用第三个:它会从自己的堆栈帧中重新抛出异常,从而丢失有关进程中原始帧的信息。

答案 3 :(得分:0)

catch (Exception) - 捕获从Exception类

派生的任何内容

catch (Exception e) - 捕获从Exception类派生的任何内容并将其分配给您可以使用的变量e。

catch - 抓住任何东西。

答案 4 :(得分:0)

示例1和2之间没有区别。两者都重新抛出原始异常,并且都捕获了常规Exception。如果您想捕获更具体的异常,例如DivisionByZeroException

,则可以使用示例1

对于最后一个例子,你没有重新抛出异常;但抛出你抓到的同一个异常对象。这会导致异常堆栈跟踪重新设置到您抛出它的位置 - 这可能是一个问题,因为堆栈跟踪不会指向实际发生错误的代码中的位置。

答案 5 :(得分:0)

不同之处在于throw e;将引发具有不同堆栈跟踪的异常。请参阅this accepted answer