为什么救援块未捕获此异常?

时间:2018-09-19 17:49:18

标签: ruby

我运行了这段代码:

begin
  print 'Enter something:'
  x = gets.to_i          # Enter a string
rescue => err
  print(err.to_s)
end

我不明白为什么救援块没有捕获到异常。它总是 输入字符串时返回零,并且不触发急救块。我不知道为什么它不起作用。谁能帮忙吗?

1 个答案:

答案 0 :(得分:4)

String#to_i和Kernel#Integer之间的行为不同

从未调用异常处理程序的原因是因为String#to_i不会引发异常,即使它无法在String对象中检测到有效的整数也是如此。在这种情况下,它仅返回func detailsRequestedForMessage(message: message) { let storyboard = UIStoryboard(name: "Additional", bundle: nil) let viewController = storyboard.instantiateViewController(withIdentifier: "MessageDetailsViewController") as! MessageDetailsViewController viewController.messageId = message.id self.navigationController?.pushViewController(viewController, animated: true) } func viewAllMessage() { let storyboard = UIStoryboard(name: "Additional", bundle: nil) let viewController = storyboard.instantiateViewController(withIdentifier: "AllMessageViewController") as! AllMessageViewController self.navigationController?.pushViewController(viewController, animated: true) } func viewOptions() { let storyboard = UIStoryboard(name: "Options", bundle: nil) let viewController = storyboard.instantiateViewController(withIdentifier: "OptionsViewController") as! OptionsViewController self.present(viewController, animated: true) }

相比之下,Kernel#Integer的行为更为复杂,但是如果字符串的内容不严格符合数字表示形式,则可能会引发ArgumentError或TypeError。

因此,为了最小化重构现有代码以在非数字输入上引发异常:

0

以下用户输入将进行清晰的转换:

  • begin print 'Enter something: ' x = Integer gets rescue => err # Do something other than just print err on STDERR, which is the # default behavior anyway. Perhaps send it to STDOUT instead. puts "I received an exception: #{err}" # After handling, re-raise the original exception with or without # passing the original exception object. `raise` and `raise err` # will do the same thing here. raise # For more advanced uses, you can also do something else like raise # a different exception (e.g. TypeError), or modify the exception # object stored in err and raise that modified object instead. end
  • 1
  • 2

在大多数情况下,该代码甚至可以处理初始/尾部空格,换行符和回车符,而无需您付出任何额外的努力。但是:

  •   

    输入一些内容:一个
      ArgumentError:Integer()的值无效:“ one \ n”

  •   

    输入内容:“ 1”
      ArgumentError:Integer()的值无效:“ \” 1 \“ \ n”

  •   

    输入内容:无
      ArgumentError:Integer()的值无效:“ nil \ n”

通常,您可以在必要时依靠Kernel#Integer引发异常,这大大简化了代码。但是,请参见下面的警告。

注意事项

这些示例不是必需的,但是您可能还需要在必要时使用#strip,#chomp或其他字符串转换来清理输入。在这方面,您的工作量会因您的实际用例而有很大不同,但是虽然Kernel#Integer通常做正确的事,并且Ruby鼓励依靠异常来处理非标准的边缘情况,但是信任用户污染的输入通常是不明智的

还值得注意的是,String#to_i和Kernel#Integer都可能对用户输入以外的值进行操作,在这种情况下,知道0xff将引发:

  

整数nil
  TypeError:无法将nil转换为Integer

这可能很重要。同样,您的里程可能会有所不同。