Sự khác biệt giữa `` raise "foo" 'và `raise Exception.new (" foo ")` là gì?


Câu trả lời:


121

Về mặt kỹ thuật, lần đầu tiên tạo ra RuntimeError với thông báo được đặt thành "foo", và lần thứ hai tạo ra Ngoại lệ với thông báo được đặt thành "foo".

Thực tế, có một sự khác biệt đáng kể giữa thời điểm bạn muốn sử dụng cái trước và khi nào bạn muốn dùng cái sau.

Nói một cách đơn giản, bạn có thể muốn RuntimeErrorkhông phải là một Exception. Khối giải cứu không có đối số sẽ bắt RuntimeErrors, nhưng KHÔNG bắt được Exceptions. Vì vậy, nếu bạn tăng một Exceptionmã của mình, mã này sẽ không bắt được nó:

begin
rescue
end

Để nắm bắt Exceptionbạn sẽ phải làm điều này:

begin
rescue Exception
end

Điều này có nghĩa là theo một nghĩa nào đó, Exceptionlỗi là một lỗi "tồi tệ hơn" so với lỗi RuntimeError, bởi vì bạn phải làm nhiều việc hơn để khôi phục nó.

Vì vậy, điều bạn muốn phụ thuộc vào cách dự án của bạn xử lý lỗi của nó. Ví dụ, trong daemon của chúng tôi, vòng lặp chính có một giải cứu trống sẽ bắt RuntimeErrors, báo cáo chúng và sau đó tiếp tục. Nhưng trong một hoặc hai trường hợp, chúng tôi muốn daemon thực sự chết vì lỗi, và trong trường hợp đó, chúng tôi tăngException , đi thẳng qua "mã xử lý lỗi bình thường" của chúng ta và ra ngoài.

Và một lần nữa, nếu bạn đang viết mã thư viện, bạn có thể muốn RuntimeError chứ không phải an Exception, vì người dùng thư viện của bạn sẽ ngạc nhiên nếu nó phát sinh lỗi mà rescuekhối trống không thể bắt được và họ sẽ mất một chút thời gian để nhận ra lý do.

Cuối cùng, tôi nên nói rằng lớp RuntimeErrorlà một lớp con của StandardErrorlớp và quy tắc thực tế là mặc dù bạn có thể raise bất kỳ loại đối tượng nào, nhưng ô trống rescuesẽ theo mặc định chỉ bắt bất kỳ thứ gì kế thừa từ đó StandardError. Mọi thứ khác phải cụ thể.


2
rất nhiều thông tin, cảm ơn. một vài điều: [1] Đoạn cuối cùng đó là đoạn sáng tỏ nhất, và hãy để tôi khám phá điều gì đó mà bạn chưa đề cập đến: RuntimeError < StandardError < Exception[2] do đó, khối mã thứ hai đó sẽ bắt được cả Exception và RuntimeError [3] Thật thú vị / kỳ lạ là việc tăng và cứu "trần" lại hoạt động với Ngoại lệ cụ thể đó [4] có lẽ quy tắc ngón tay cái là nâng RuntimeError lên mã máy khách, nhưng nâng và giải cứu các Ngoại lệ tùy chỉnh của riêng mình trong mã của riêng mình?
John Bachir

1
[1, 2] Đúng. [3] không chắc ... [4] Khi tôi viết mã chuyên nghiệp nhất, tôi có xu hướng tạo các loại lỗi tùy chỉnh kế thừa từ đó StandardError. Nó không cần phải phức tạp hơn một vài dòng như thế class MissingArgumentsError < StandardError; end.
Daniel Lucraft

Rất nhiều thông tin, nhưng trong những loại tình huống nào mà bạn sẽ muốn ném một Ngoại lệ thay vì lỗi thời gian chạy nếu lỗi thời gian chạy được ưu tiên cho việc viết thư viện?
Chihung Yu

35

Từ tài liệu chính thức:

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

Không có đối số, tăng ngoại lệ trong $!hoặc tăng một RuntimeErrorif $!là nil. Với một Stringđối số duy nhất , nó tăng a RuntimeErrorvới chuỗi dưới dạng một thông báo. Nếu không, tham số đầu tiên phải là tên của một Exceptionlớp (hoặc một đối tượng trả về Exceptionngoại lệ khi được gửi). Tham số thứ hai tùy chọn đặt thông báo được liên kết với ngoại lệ và tham số thứ ba là một mảng thông tin gọi lại. Các ngoại lệ được nắm bắt bởi điều khoản giải cứu của begin...endcác khối.

raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.