在Ruby中提高异常与抛出异常有什么区别?

Nic*_*ack 160 ruby exception

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

为什么我们有两个?

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

Jar*_*eck 103

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

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

终止单级控制流,如while循环,可以通过简单的方式完成return.终止许多级别的控制流,如嵌套循环,可以完成throw.

虽然引发和救援的异常机制非常适合在出现问题时放弃执行,但有时候能够在正常处理期间跳出一些深度嵌套的构造是很好的.这就是捕获和投掷派上用场的地方.(Thomas和Hunt,2001)

参考

  1. 格林,阿夫迪."投掷,抓住,提升,救援......我很困惑!" RubyLearning博客.Np,2011年7月11日.网站.2012年1月1日.http ://rubylearning.com/blog/2011/07/12/throw-catch-raise-rescue--im-so-confused/.
  2. 托马斯,戴夫和安德鲁亨特."Ruby编程." :实用程序员指南.Np,2001.Web.2015年9月29日.http ://ruby-doc.com/docs/ProgrammingRuby/html/tut_exceptions.html.

  • Avdi看起来不像播客中的声音. (2认同)
  • Ruby Learning链接似乎不起作用.这是另一篇讨论差异的博客文章:http://danielchangnyc.github.io/blog/2013/10/23/throw-raise/ (2认同)

Rea*_*nly 101

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

catch/throw与raise/rescue不同.catch/throw允许您快速退出块返回到为特定符号定义catch的点,raise rescue是涉及Exception对象的真正异常处理内容.

  • 另外值得一提的是:`raise`非常昂贵.`throw`不是.把`throw`想象成使用`goto`来摆脱循环. (10认同)
  • @Denis你指的是哪些陷阱? (4认同)
  • 链接失效了! (4认同)

Mar*_*ery 19

https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise提供了一个很好的解释,我怀疑我可以改进.总结一下,在我去的时候从博客文章中删除一些代码示例:

  1. raise/ rescue是与其他语言(或Python的/ )熟悉的throw/ catch构造最接近的类似物.如果你遇到了一个错误条件而你会用另一种语言覆盖它,你应该在Ruby中.raiseexceptthrowraise

  2. Ruby's throw/ catch允许你打破执行并爬上堆栈寻找catch(喜欢raise/ rescue确实),但并不真正意味着错误条件.它应该很少使用,并且只是当"向上移动堆栈直到找到相应的catch"行为对于您正在编写的算法有意义但是将其throw视为对应于错误是没有意义的条件.

    什么是Ruby中的catch和throw?提供了关于throw/ catchconstruct的良好用法的一些建议.

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

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

    catch("foo") do
      throw "foo"
    end
    
    Run Code Online (Sandbox Code Playgroud)

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

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

    begin
      do_something_error_prone
    rescue AParticularKindOfError
      # Insert heroism here.
    rescue
      write_to_error_log
      raise
    end
    
    Run Code Online (Sandbox Code Playgroud)

    而多个catches需要嵌套...

    catch :foo do
      catch :bar do
        do_something_that_can_throw_foo_or_bar
      end
    end
    
    Run Code Online (Sandbox Code Playgroud)
  • 裸露rescue等同于rescue StandardError并且是惯用的构造.catch像"裸"一样catch() {throw :foo},永远不会捕获任何东西,不应该使用.

  • @ wired00:自从1960年代首次对结构化错误处理进行实验以来,它就被称为“引发”异常,在发明了现代形式的异常处理的开创性文章中,它被称为“引发”异常。在Lisps和Smalltalks中“引发”异常是Ruby的主要灵感,它被称为“引发”异常或“引发”硬件中断,在硬件中,该概念甚至早于“编程”概念就存在。语言”。问题应该是:那些其他语言为什么会改变这种状况? (2认同)