题
Ruby 有两种不同的异常机制:投掷/接住和举起/救援。
为什么我们有两个?
什么时候应该使用其中一种而不是另一种?
解决方案
我认为 http://hasno.info/ruby-gotchas-and-caveats 对差异有一个很好的解释:
catch/ throw 与 raise/rescue 不同。catch / throw允许您快速退出块回到为特定符号定义catch的点,引发救援是涉及Exception对象的真正异常处理内容。
其他提示
raise
,fail
,rescue
, , 和ensure
处理 错误, ,也称为 例外情况throw
和catch
是 控制流
与其他语言不同,Ruby's的投掷和捕获不用于例外。相反,当不需要进一步的工作时,它们提供了一种尽早终止执行的方法。(格林,2011)
终止单个级别的控制流,例如 while
循环,可以用一个简单的方法来完成 return
. 。终止多个级别的控制流(例如嵌套循环)可以通过以下方式完成 throw
.
虽然引发和救援的异常机制非常适合在出现问题时放弃执行,但有时在正常处理期间能够跳出某些深度嵌套的构造也很好。这就是 catch 和 throw 派上用场的地方。(托马斯和亨特,2001)
参考
- 格林,阿夫迪。“投掷,捕捉,举起,救援……我很困惑!” RubyLearning博客。N.p.,2011 年 7 月 11 日。网络。1 月 1 日2012年。 http://rubylearning.com/blog/2011/07/12/throw-catch-raise-rescue--im-so-confused/.
- 托马斯、戴夫和安德鲁·亨特。“编程Ruby。” :实用程序员指南。N.p.,2001 年。网络。9 月 29 日2015年。 http://ruby-doc.com/docs/ProgrammingRuby/html/tut_exceptions.html.
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s- throw-statement-with-raise 提供了一个很好的解释,我怀疑我是否可以改进。总而言之,我从博客文章中摘录了一些代码示例:
raise
/rescue
是最接近的类似物throw
/catch
从其他语言(或 Python 的raise
/except
)。如果您遇到错误情况并且您会throw
用另一种语言来代替它,你应该raise
在红宝石中。红宝石的
throw
/catch
让你中断执行并爬上堆栈寻找catch
(喜欢raise
/rescue
确实如此),但并不真正意味着错误情况。它应该很少使用,并且只是在“沿着堆栈向上走直到找到相应的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"
(或一个ArgumentError
在 2.2 之前的 Ruby 版本中)可以列出多个救援条款...
begin do_something_error_prone rescue AParticularKindOfError # Insert heroism here. rescue write_to_error_log raise end
同时多个
catch
es 需要嵌套...catch :foo do catch :bar do do_something_that_can_throw_foo_or_bar end end
一个裸露的
rescue
相当于rescue StandardError
并且是一个惯用的结构。一个“裸catch
“, 喜欢catch() {throw :foo}
, ,永远不会捕获任何东西,也不应该使用。