当 Ruby 中出现第二个异常时,如何让旧的引用生效?

Posted

技术标签:

【中文标题】当 Ruby 中出现第二个异常时,如何让旧的引用生效?【英文标题】:How to get the reference alive to the older one, when there is a second exception in Ruby? 【发布时间】:2013-01-25 03:27:17 【问题描述】:
begin
  raise "explosion"
rescue
  p $!
  raise "Are you mad"
  p $!
end

# #<RuntimeError: explosion>
# RuntimeError: Are you mad
#    from (irb):5:in `rescue in irb_binding'
#    from (irb):1
#    from /usr/bin/irb:12:in `<main>'

$! 始终只保存当前异常对象引用。

但是在引发另一个异常之后,有什么方法可以获取对原始异常对象的引用(这里是“爆炸”)?

我自己尝试并得到了答案,希望现在对我的问题处于Smokey情况的所有人来说更清楚。

【问题讨论】:

您可能会被否决,因为您的要求非常不清楚。包含一个期望结果应该是什么的样本是个好主意。在这种情况下,您想对原始异常做什么?你不抢救第二个异常,那为什么又要原来的异常呢?当人们不得不猜测你可能想要什么时,他们往往会投反对票。 @TheMiddleMan Andrew Marshall 的编辑使您的问题变得清晰,但现在您添加了一个额外的段落,没有添加任何新信息,并且您的英语蹩脚再次使其不清楚。 我也给出了答案。也谢谢你们。 @sawa 你能告诉我现在出了什么问题吗,我也发布了我的答案。那么现在理解我在寻找什么的困惑是什么?如果还有什么烟雾,请告诉我。 @TheMiddleMan 我的错;我道歉。正如布拉德指出的那样,我们一直看到这样的帖子,这些帖子用于为原始问题添加额外的代码/细节。您可以通过补充您的代码并解释它是什么以及它如何解决您的问题来帮助我们避免混淆。 【参考方案1】:

您是说在挽救第二个异常时要参考原始异常吗?如果是这样,那么您需要在救援期间在变量中捕获原始异常。这是通过这样做来完成的:

rescue StandardError => e

其中 StandardError 可以是任何类型的异常或省略(在这种情况下 StandardError 是默认值)。

例如代码:

begin
    raise "original exception"
rescue StandardError => e
    puts "Original Exception:"
    puts $!
    puts e
    begin
        raise "second exception"
    rescue
        puts "Second Exception:"
        puts $!
        puts e      
    end
end

给出输出:

Original Exception:
original exception
original exception
Second Exception:
second exception
original exception

如您所见,e 已经存储了原始异常以供第二个异常之后使用。

【讨论】:

【参考方案2】:
class MyError < StandardError
attr_reader :original
def initialize(msg, original=$!)
super(msg)
@original = original;
end
end
begin
    begin
    raise "explosion"
    rescue => error
    raise MyError, "Are you mad"
    end
rescue => error
puts "Current failure: #error.inspect"
puts "Original failure: #error.original.inspect"
end

输出

Current failure: #<MyError: Are you mad>
Original failure: #<RuntimeError: explosion>
=> nil

【讨论】:

以上是关于当 Ruby 中出现第二个异常时,如何让旧的引用生效?的主要内容,如果未能解决你的问题,请参考以下文章

对 ITVF 的引用会引发“在前一个操作完成之前在此上下文上启动的第二个操作”异常

当我尝试添加第二个活动时未处理的事件循环异常

在不使用导航控制器的情况下转到第二个视图时如何显示动画?

当任何数学运算在 .net 4 中产生“NaN”时,如何强制 C# 编译器抛出异常?

为啥在第一个连接结束后创建第二个连接会导致管道异常?

如何合并两个可观察的早期完成