[英]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無法在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.