在处理错误时,在啥意义上,使用异常比使用 if...else...switch... 等更好?

Posted

技术标签:

【中文标题】在处理错误时,在啥意义上,使用异常比使用 if...else...switch... 等更好?【英文标题】:When it comes to handle errors, in what sense, using Exceptions are better that utilize if...else...switch... etc.?在处理错误时,在什么意义上,使用异常比使用 if...else...switch... 等更好? 【发布时间】:2016-04-29 22:38:18 【问题描述】:

我完全理解 (try/throw/catch) 块的细微差别。

我不明白的是:

如果我们无论如何要在try 块中使用IF(或任何控制结构)来测试是否满足条件,那么只有在该测试结果的情况下,'throw' 才会出现异常是假的,那么......在我看来:抛出/生成异常是无用的;因为如果不满足某个条件,我们可以简单地打印一条错误消息、调用一个函数、实例化一个类、重定向到另一个位置等等。

另一个故事是,例如,如果一个变量未初始化,我们将该变量包含在一个 try 块中,回显该变量,从那时起,一切都将由 catch() 块处理,因为try 块引发错误;并且由于try/catch 块相互交谈,catch 块将捕获源自其相应 try 块的每个错误。但是,您可以在 try 块中设置自定义错误消息(可选)。

到目前为止我读过的内容: 每个搜索结果:if vs. try

我确实看到了区别。

但我不明白为什么有些人选择try/throw/catch 而不是if...else...switch...while...等等。

据我所知,try/throw/catch 可用于调试。

【问题讨论】:

Exceptions are ehm...exception 这意味着您永远无法编写尽可能多的if 语句来覆盖所有可能的错误路径。此外,异常是范围不敏感的。如果您使用 - 比方说 - 使用无效文件指针的函数,然后在代码中使用此函数,您将无法在外部范围内显式验证指针。异常会通过作用域冒泡到第一个 try..catch 块。 @TeKo 我明白你的意思,但在你的例子中,有很多文件处理函数来管理这种情况。我仍然看不到try/catch 的用处。 是的,但是您必须在可能的最低范围(使用它的函数)中验证所述指针,并且此处做出的任何错误处理决定都会影响每个不太灵活的外部范围。 任何函数,都应该尽可能地与主代码隔离,使最终程序的骨架尽可能模块化。也就是说,您可以使用自定义错误处理函数,但不能从一个地方处理所有错误。内在子程序的逻辑必须保持内在。恕我直言。 【参考方案1】:

if/then 相比,异常的一个好处是您可以将try/catch 包裹在一大块代码中。如果块中的任何地方发生错误,它将被触发。

try 
    $db = db_open();
    $statement = $db->prepare($sql);
    $result = $statement->execute($params);
 catch (Exception $e) 
    die($e->getMessage());

使用if/then,您必须在每一步执行测试。

$db = db_open();
if (!$db) 
    die(db_connect_error());

$statement = $db->prepare($sql);
if (!$statement) 
    die(db_error($db));

$result = $statement->execute($params);
if (!$result) 
    die(db_error($db));

【讨论】:

正是巴马尔。您的示例补充了@CharlotteDunois 关于重大错误的说法。现在我可以看得更清楚了。谢谢你=*** 谢谢大家=***【参考方案2】:

正如您所说,在 try/catch 块中抛出异常并立即捕获它会产生很多开销。

try 
  if (...) 
    // good, do no throw
   else 
    throw new Exception();
  
 catch ($e) 
  // handle exception

这应该替换为:

if (...) 
  // good
 else 
  // handle error, no exception

异常很有用,因为它们会冒泡。所以想象一下,如果你有这个代码:

function bla() 
  try 
    tryToDoSomething();
   catch ($e) 
    // handle error
  


function tryToDoSomething() 
  if ($somethingNotAvailable) 
    throw new Exception();
  
  doSomething();

在这种情况下,定义 try/catch 的函数不是引发异常的函数。 tryToDoSomething() 不知道如何处理错误,所以它会让父方法来处理它。异常可以在调用堆栈中冒泡,直到有人捕获它并处理错误。这就是异常实际上有用的方式:)

【讨论】:

阿德里安,差不多。我在您的示例中看到的是一个调试场景。因为如果$somethingNotAvailable,我,(作为医生),需要知道为什么不可用。我将在哪里找到答案?谁来告诉我发生了什么?:Exception 机制。 异常不用于调试。当常规控制流无法继续时使用异常,例如由于一个巨大的错误。 @klymax 不是。异常主要只是向外部作用域发出回滚到最近的安全点并优雅地死亡的信号。 我知道@TeKo,正如我所说:我完全理解 (try/throw/catch) 块的细微差别。 你说出了神奇的话@CharlotteDunois:“一个巨大的错误”。而且我知道异常不能用于调试,但不能用于测试一个小函数是否可以或不能做某事。

以上是关于在处理错误时,在啥意义上,使用异常比使用 if...else...switch... 等更好?的主要内容,如果未能解决你的问题,请参考以下文章

Elixir 和 Julia 之类的语言在啥意义上是谐音的?

异常处理

memcpy在啥情况下会失败

memcpy在啥情况下会失败

异常处理

java是如何处理异常的?