Ruby有两种不同的异常机制:Throw/Catch和Raise/Rescue.
为什么我们有两个?
什么时候应该使用一个而不是另一个?
raise
,fail
,rescue
,和ensure
处理错误,也被称为异常
throw
并且catch
是控制流程
与其他语言不同,Ruby的throw和catch不用于异常.相反,它们提供了一种在不需要进一步工作时提前终止执行的方法.(格林,2011)
终止单级控制流,如while
循环,可以通过简单的方式完成return
.终止许多级别的控制流,如嵌套循环,可以完成throw
.
虽然引发和救援的异常机制非常适合在出现问题时放弃执行,但有时候能够在正常处理期间跳出一些深度嵌套的构造是很好的.这就是捕获和投掷派上用场的地方.(Thomas和Hunt,2001)
格林,阿夫迪."投掷,抓住,提升,救援......我很困惑!" RubyLearning博客.Np,2011年7月11日.网站.2012年1月1日.http ://rubylearning.com/blog/2011/07/12/throw-catch-raise-rescue--im-so-confused/.
托马斯,戴夫和安德鲁亨特."Ruby编程." :实用程序员指南.Np,2001.Web.2015年9月29日.http ://ruby-doc.com/docs/ProgrammingRuby/html/tut_exceptions.html.
我认为http://hasno.info/ruby-gotchas-and-caveats对差异有一个不错的解释:
catch/throw与raise/rescue不同.catch/throw允许您快速退出块返回到为特定符号定义catch的点,raise rescue是涉及Exception对象的真正异常处理内容.
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise提供了一个很好的解释,我怀疑我可以改进.总结一下,在我去的时候从博客文章中删除一些代码示例:
raise
/ rescue
是与其他语言(或Python的/ )熟悉的throw
/ catch
构造最接近的类似物.如果你遇到了一个错误条件而你会用另一种语言覆盖它,你应该在Ruby中.raise
except
throw
raise
Ruby's throw
/ catch
允许你打破执行并爬上堆栈寻找catch
(喜欢raise
/ rescue
确实),但并不真正意味着错误条件.它应该很少使用,并且只是当"向上移动堆栈直到找到相应的catch
"行为对于您正在编写的算法有意义但是将其throw
视为对应于错误是没有意义的条件.
什么是Ruby中的catch和throw?提供了关于throw
/ catch
construct的良好用法的一些建议.
它们之间具体的行为差异包括:
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}
,永远不会捕获任何东西,不应该使用.