是否存在一般性E未捕获的异常:异常?

时间:2014-08-18 08:10:44

标签: delphi exception exception-handling

我想知道是否存在异常/错误,这会使您的代码跳转到一个except块但不会被E:exception处理。

 try
   i := StrToInt(s);
   {...do a lot more...}
 except
   on E : EConvertError do begin
     ShowMessage('You need to input a valid number.');
   end;
   on E : Exception do begin
     ShowMessage('Something went wrong.');
     Raise; 
   end;
 end;

是否有一种程序可能会出现错误,忽略此块中的两个语句? 或者我应该这样做:

 try
   i := StrToInt(s);
   {...do a lot more...}
 except
   on E : EConvertError do begin
     ShowMessage('You need to input a valid number.');
   end;
   else begin  // swapped on e : Exception with else
     ShowMessage('Something went wrong.');
     Raise; 
   end;
 end;

1 个答案:

答案 0 :(得分:7)

你可以抛出任何来自TObject的东西。为了捕获每个这样的类,您需要在TObject语句中指定on

来自documentation

  

异常类型的声明与其他类一样。实际上,可以使用任何类的实例作为异常,但建议从SysUtils中定义的SysUtils.Exception类派生异常。

实际上,我知道没有任何代码可以抛出任何不是Exception的代码,尽管@TLama在评论中指出了旧版已弃用的VCL类中的一个示例。当然StrToInt只会抛出Exception后代。

如果您不需要访问异常对象,则可以使用普通except子句而不使用on语句。

try
  ....
except 
  // deal with all exceptions
end;

或者您可以使用else语句的on子句作为catch all,同样您将无法立即访问异常对象。

否则,您可以为要捕获的异常指定基类。例如,on E: TObject捕获从TObject派生的所有内容。

因此,正如我们所看到的,可能会抛出非Exception派生的内容。但你必须问自己,你的代码是否曾经这样做过?如果没有,则最有必要在捕获所有处理程序中测试Exception。这样您就可以访问Exception的成员。当然,人们确实想知道为什么你有一个捕获所有异常处理程序。它们的存在往往表明设计不佳。

继续StrToInt的主题,您只需要抓住EConvertError。这就是转换失败时引发的问题。您应该忽略任何其他异常类,因为在您的示例中,代码将不知道如何处理其他任何异常。编写异常处理代码的目标之一是处理您知道如何处理的内容,并忽略其他所有内容。

事实上,TryStrToInt就是您所需要的:

if TryStrToInt(s, i) then
  // do stuff with i
else
  // deal with conversion error

这消除了处理任何异常的需要,并使您的代码更具可读性。

我知道StrToInt只是一个例子,但它很好地证明了试图避免处理异常的好处。