186

Ruby 有两种不同的异常机制:Throw/Catch 和 Raise/Rescue。

为什么我们有两个?

什么时候应该使用一个而不是另一个?

4

3 回答 3

125
  • raise, fail, rescue, 和ensure处理错误,也称为异常
  • throw并且catch控制流

与其他语言不同,Ruby 的 throw 和 catch 不用于异常。相反,它们提供了一种在不需要进一步工作时提前终止执行的方法。(格林,2011)

while可以使用简单的return. 终止多层控制流,如嵌套循环,可以使用throw.

虽然 raise 和 rescue 的异常机制非常适合在出现问题时放弃执行,但在正常处理期间能够跳出一些深度嵌套的构造有时会很好。这就是 catch 和 throw 派上用场的地方。(托马斯和亨特,2001)

参考

  1. 格林,阿维迪。“投、接、举、救……我好糊涂!” Ruby 学习博客。Np,2011 年 7 月 11 日。网络。2012 年 1 月 1 日。http ://rubylearning.com/blog/2011/07/12/throw-catch-raise-rescue--im-so-confused/
  2. 托马斯、戴夫和安德鲁·亨特。“编程红宝石。” : 实用程序员指南。Np,2001 年。网络。2015 年 9 月 29 日。http ://ruby-doc.com/docs/ProgrammingRuby/html/tut_exceptions.html
于 2012-01-01T06:18:28.930 回答
112

我认为http://hasno.info/ruby-gotchas-and-caveats对差异有一个不错的解释:

接/投与举/救不同。catch/throw 允许您将块快速退出到为特定符号定义捕获的点,引发救援是涉及 Exception 对象的真正异常处理内容。

于 2008-09-09T00:50:02.753 回答
22

https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise提供了一个很好的解释,我怀疑我可以改进。总而言之,我从博客文章中截取了一些代码示例:

  1. raise/是您从其他语言(或 Python 的/ )熟悉的/构造rescue最接近的类似物。如果您遇到了错误情况并且您将使用另一种语言来解决它,那么您应该使用 Ruby。throwcatchraiseexceptthrowraise

  2. Ruby 的throw/catch让你中断执行并爬上堆栈寻找catch(like raise/ rescuedos),但实际上并不意味着错误条件。它应该很少使用,并且仅用于当“遍历堆栈直到找到相应的catch”行为对您正在编写的算法有意义但将其throw视为对应于错误是没有意义的健康)状况。

    Ruby 中的 catch 和 throw 有什么用?throw提供了一些关于/catch构造的好用的建议。

它们之间的具体行为差异包括:

  • rescue Foo将拯救Foo包括Foo. catch(foo)只会捕获相同的对象,Foo . 您不仅不能传递catch类名来捕获它的实例,而且它甚至不会进行相等比较。例如

    catch("foo") do
      throw "foo"
    end
    

    会给你一个UncaughtThrowError: uncaught throw "foo"(或ArgumentError2.2 之前的 Ruby 版本)

  • 可以列出多个救援条款...

    begin
      do_something_error_prone
    rescue AParticularKindOfError
      # Insert heroism here.
    rescue
      write_to_error_log
      raise
    end
    

    而多个catches需要嵌套...

    catch :foo do
      catch :bar do
        do_something_that_can_throw_foo_or_bar
      end
    end
    
  • 一个barerescue等价于rescue StandardError并且是一个惯用的构造。“裸catch”,如catch() {throw :foo},永远不会捕获任何东西,也不应该使用。

于 2014-12-03T16:42:02.623 回答