簡體   English   中英

為什么救援塊未捕獲此異常?

[英]Why is this exception not being caught by the rescue block?

我運行了這段代碼:

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

我不明白為什么救援塊沒有捕獲到異常。 輸入字符串時,它始終返回零,並且不觸發救援塊。 我不知道為什么它不起作用。 誰能幫忙嗎?

String#to_i和Kernel#Integer之間的行為差​​異

永遠不會調用您的異常處理程序的原因是,即使String#to_i無法在String對象中檢測到有效的整數,它也不會引發異常。 在這種情況下,它僅返回0

相比之下, Kernel#Integer的行為更為復雜,但是如果字符串的內容不嚴格符合數字表示形式,則可能會引發ArgumentError或TypeError。

因此,為了最小化重構現有代碼以在非數字輸入上引發異常:

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
  • 0xff

在大多數情況下,該代碼甚至可以處理初始/尾部空格,換行符和回車符,而無需您付出任何額外的努力。 然而:

  • 輸入一些:
    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都可能對用戶輸入以外的值進行操作,在這種情況下,請注意Integer(nil)將引發:

無整數
TypeError:無法將nil轉換為Integer

這可能很重要。 同樣,您的里程可能會有所不同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM