`raise "foo"` 和 `raise Exception.new("foo")` 有啥区别?

Posted

技术标签:

【中文标题】`raise "foo"` 和 `raise Exception.new("foo")` 有啥区别?【英文标题】:What is the difference between `raise "foo"` and `raise Exception.new("foo")`?`raise "foo"` 和 `raise Exception.new("foo")` 有什么区别? 【发布时间】:2011-06-15 14:26:08 【问题描述】:

两者之间有什么区别——技术、哲学、概念或其他方面

raise "foo"

raise Exception.new("foo")

?

【问题讨论】:

【参考方案1】:

From the offical documentation:

raise   
raise( string )
raise( exception [, string [, array ] ] )

不带参数,在$! 中引发异常,如果$! 为nil,则引发RuntimeError。使用单个 String 参数,它会引发 RuntimeError 并将字符串作为消息。否则,第一个参数应该是Exception 类的名称(或在发送异常时返回Exception 的对象)。可选的第二个参数设置与异常关联的消息,第三个参数是回调信息数组。异常被 begin...end 块的救援子句捕获。

raise "Failed to create socket"
raise ArgumentError, "No parameters", caller

【讨论】:

【参考方案2】:

从技术上讲,第一个引发 RuntimeError 并将消息设置为 "foo",第二个引发一个异常并将消息设置为 "foo"

实际上,您想要使用前者的时间和想要使用后者的时间之间存在显着差异。

简单地说,您可能需要RuntimeError 而不是Exception。没有参数的救援块将捕获RuntimeErrors,但不会捕获Exceptions。因此,如果您在代码中提出Exception,此代码将无法捕获它:

begin
rescue
end

为了赶上Exception,您必须这样做:

begin
rescue Exception
end

这意味着在某种意义上,Exception 是一个比RuntimeError 更“糟糕”的错误,因为您必须做更多的工作才能从中恢复。

所以你想要什么取决于你的项目如何处理它的错误。例如,在我们的守护进程中,主循环有一个空白救援,它将捕获RuntimeErrors,报告它们,然后继续。但在一两种情况下,我们希望守护进程真正死于错误,在这种情况下,我们会引发Exception,它会直接通过我们的“正常错误处理代码”并退出。

同样,如果您正在编写库代码,您可能需要RuntimeError,而不是Exception,因为如果它引发空白rescue 块无法捕获的错误,您的库用户会感到惊讶,他们需要一点时间才能意识到原因。

最后,我应该说RuntimeErrorStandardError 类的子类,而实际的规则是虽然你可以raise any 类型的对象,但空白的@默认情况下,987654341@ 只会捕获从StandardError 继承的任何内容。其他一切都必须具体。

【讨论】:

非常有用,谢谢。一些事情:[1] 最后一段是最有启发性的,让我在 irb 发现一些你没有提到的东西:RuntimeError < StandardError < Exception [2] 因此,第二个代码块捕获异常和 RuntimeError [3] 有趣/奇怪的是,“裸”引发和救援恰好与特定异常 [4] 一起工作,也许经验法则是将 RuntimeError 引发到客户端代码,但引发和救援自己的代码在自己的代码中自定义异常? [1, 2] 是的。 [3] 不确定... [4] 当我最专业地编写代码时,我倾向于创建从StandardError 继承的自定义错误类型。它不必比像class MissingArgumentsError < StandardError; end 这样的几行更复杂。 信息量很大,但是如果在编写libraray时首选运行时错误,那么在什么情况下你会想要抛出异常而不是运行时错误?

以上是关于`raise "foo"` 和 `raise Exception.new("foo")` 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

如何解决 raise ValueError("columns must have matching element counts") ValueError: columns mus

jpype测试报错,找不到类raise _RUNTIMEEXCEPTION.PYEXC("Class %s not found" % name)

函数 foo(param) alert("foo 调用"); 和 $scope.foo = function(param)alert("foo");;

python pip安装 mysqlclient 报错 raise EnvironmentError("%s not found" % (_mysql_config_path,))

raise ValueError("Unknown label type: %s" % repr(ys)) ValueError: Unknown label type: (arr

比较 $("#foo .bar") 和 $(".bar", "#foo") 的性能