最衍生的例外是什么?

时间:2011-01-06 12:56:32

标签: c# exception


我还有另一个问题,我找不到答案。我知道捕获块的顺序是从最普遍的到最普遍的 但我不明白为什么我可以这样做(为什么这个命令有效?formatException派生自Exception,所以它更通用,对吗?)

catch(formatException)
//this is derived from Exception

catch(OutoFMemoryException) 
// this is derived from ArithmeticException whic is derived from Exception

9 个答案:

答案 0 :(得分:2)

CLR按照提供的顺序逐步执行catch块。

如果它找到一个带有与当前异常匹配的异常类型的catch语句或者从当前异常继承的异常,那么将调用该块。

答案 1 :(得分:2)

您必须从最具体的例外转到最常见的例外。

例如,在下面的代码中:

int x = 4 / (1 - 1);

您将获得DivideByZeroException类型的例外,它是一个ArithmeticException,这是一个例外。

那你怎么用呢?

如果您知道可以获得某些类型的错误,则可以在每个错误发生时添加特定代码。

如果你知道你可以获得DivideByZeroException,你可以为它设置一个catch块,并按照你应该的方式对待它。您还应该为更常见的异常类型添加一个catch:

try
{
    int x = 4 / (1 - 1);
    // More Stuff
}
catch(DivideByZeroException ex)
{
    // Here we know we got an exception on that division
}
catch(Exception ex)
{
   // Here we know something went wrong on that "more stuff"
}

您可以通过这种方式轻松解决问题。

答案 2 :(得分:1)

不是必须的,即使OverflowException派生自ArithmeticException,他们最常见的分母是Exception

您可以将其视为某种树结构,其中FormatExceptionOverflowException位于树的不同侧。如果从OverflowException继承的FormatException情况会有所不同,但事实并非如此。

另外,你可以按不同的顺序排列它们但是没有意义,因为如果你有一个更普遍的例外,它首先会捕获它下面的每个异常。

答案 3 :(得分:1)

它还取决于抛出的异常类型,它将决定调用哪个catch块。由于您定义了FormatException的catch,因此如果抛出FormatException,只有在Exception catch没有定义之前,它才会被该catch捕获。如果您没有定义FormatException catch,那么Exception catch将处理FormatException,因为它来自Exception

答案 4 :(得分:1)

try-catch语句包含一个try块,后跟一个或多个catch子句,这些子句为不同的异常指定处理程序。

抛出异常时,公共语言运行库(CLR)会查找处理此异常的catch语句。

如果当前正在执行的方法不包含这样的catch块,则CLR会查看调用当前方法的方法,依此类推调用堆栈。

如果未找到catch块,则CLR会向用户显示未处理的异常消息并停止执行该程序。

以上找到@ msdn

CLR在可以处理异常的第一个catch块停止。无论哪一个在列表中排在第一位。

答案 5 :(得分:1)

例如,使用这段代码。您应该始终首先使用最具体的异常,然后在最后使用最常见的异常。或者我相信我可以说,就像你说的那样 - 最先导出的例外。

在这种情况下,第一个catch块已经捕获了这个或超类型的所有异常('System.Exception')“。这就是异常订单的原因。

try
{
 throw new formatException();
}


catch(Exception ex)
{
    <...>
}
catch(formatException ex)
{
    <...>
}

编辑 -

如果查看FormatException类的继承层次结构 -

  System.Exception
    System.SystemException
      System.FormatException

和OutOfMemoryException类的继承层次结构是 -

  System.Exception
    System.SystemException
      System.OutOfMemoryException

只有当catch块具有彼此的基类或派生类的异常类时,才会出现异常优先顺序。

例如如果你有两个catch块 - FormatException和Exception,那么你需要担心catch块的顺序,因为FormatException类继承自Exception类。 如果在FormatException catch块之前放置Exception catch块,则异常捕获块将捕获每个异常(甚至是格式异常)。 如果在Exception catch块之前有FormatException catch块,则特定的FormatException catch块会捕获格式异常,但异常捕获块会捕获所有其他异常。

但是,如果你有两个catch块,比如FormatException和OutOfMemoryException。然后您不必担心订单,因为这两个类不是基础或相互派生。所以,它们只是特定的例外。

所以,你可以有 -

try
{
 throw new formatException();
}
catch(OutOfMemoryException ex)
{
    <...>
}
catch(FormatException ex)
{
    <...>
}

try
{
 throw new formatException();
}  
catch(FormatException ex)
{
    <...>
}
catch(OutOfMemoryException ex)
{
    <...>
}

它没有什么区别,因为无论顺序是什么,formatexception总是被特定的FormatException catch块捕获。它与OutOfMemoryException相同。我希望这回答了你的问题。

答案 6 :(得分:0)

它适用于层次结构,OverflowExceptiona和FormatException位于不同的分支上,并且只共享公共的Exception类。

答案 7 :(得分:0)

关键是Subclass将首先出现,然后是Base class

答案 8 :(得分:0)

@Loj,你可以在概念上将catch语句看作switch语句(我们不能写这样的switch语句,但仍然如此):

switch (caughtException) 
{ 
   case (caughtException is FormatException):...;
   case (caughtException is OverflowException):...; 
   case (caughtException is Exception):...; 
   etc.  

第一个完成“是”检查的类型将是处理异常的类型。这就是为什么你需要注意catch块的顺序。 Catch块是从最具体到最一般的指定,因为这是确保我们不会混淆自己的最佳方法。

在您的示例中,OutOfMemoryException在“异常”中被“进一步删除”而不是FormatException,但这不会产生问题,因为检查caughtException is FormatException返回false,我们继续下一个可能性。