我还有另一个问题,我找不到答案。我知道捕获块的顺序是从最普遍的到最普遍的
但我不明白为什么我可以这样做(为什么这个命令有效?formatException派生自Exception,所以它更通用,对吗?)
catch(formatException)
//this is derived from Exception
catch(OutoFMemoryException)
// this is derived from ArithmeticException whic is derived from Exception
答案 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
。
您可以将其视为某种树结构,其中FormatException
和OverflowException
位于树的不同侧。如果从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,我们继续下一个可能性。