Какая разница - технические, философские, концептуальные, или иначе - междуВ чем разница между `raise 'foo" и `raise Exception.new (" foo ")`?
raise "foo"
и
raise Exception.new("foo")
?
Какая разница - технические, философские, концептуальные, или иначе - междуВ чем разница между `raise 'foo" и `raise Exception.new (" foo ")`?
raise "foo"
и
raise Exception.new("foo")
?
Технически, первый поднимает RuntimeError с сообщением, установленным в "foo"
, а второй вызывает исключение с сообщением, установленным в "foo"
.
Практически существует существенная разница между тем, когда вы хотите использовать первое и когда хотите использовать последний.
Проще говоря, вы, вероятно, хотите RuntimeError
не Exception
. Блок спасения без аргумента поймает RuntimeErrors
, но НЕ поймает Exception
s. Так что если вы поднять Exception
в код, этот код не будет поймать его:
begin
rescue
end
Для того, чтобы поймать Exception
вам придется это сделать:
begin
rescue Exception
end
Это означает, что в некотором смысле , Exception
является «худшей» ошибкой, чем RuntimeError
, потому что вам нужно сделать больше работы, чтобы оправиться от нее.
Так что вы хотите, зависит от того, как ваш проект справляется с ошибками. Например, у наших демонов основной цикл имеет пустое спасение, которое поймает RuntimeErrors
, сообщит об этом, а затем продолжит. Но в одном или двух случаях мы хотим, чтобы демон действительно действительно умирал от ошибки, и в этом случае мы поднимаем Exception
, который проходит прямо через наш «нормальный код обработки ошибок» и выходит.
И опять же, если вы пишете код библиотеки, вы, вероятно, хотите RuntimeError
, не Exception
, так как пользователи вашей библиотеки будут удивлены, если это вызывает ошибки, пустой rescue
блок не может поймать, и он будет принимать им нужно понять, почему.
Наконец, я должен сказать, что RuntimeError
является подклассом StandardError
класса, а фактическое правило таково, что, хотя вы можете raise
любой типа объекта, заготовка rescue
будет по умолчанию только поймать что-нибудь, что наследуется от StandardError
,Все остальное должно быть конкретным.
From the offical documentation:
raise
raise(string)
raise(exception [, string [, array ] ])
без аргументов, вызывает исключение в $!
или поднимает RuntimeError
если $!
равна нулю. С одним аргументом String
он поднимает RuntimeError
со строкой в виде сообщения. В противном случае первым параметром должно быть имя класса Exception
(или объект, который возвращает Exception
при отправленном исключении). Второй необязательный параметр устанавливает сообщение, связанное с исключением, а третий параметр представляет собой массив информации обратного вызова. Исключения попадают в резервную позицию блоков begin...end
.
raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
очень информативный, спасибо. несколько вещей: [1] Последний абзац был самым ярким, и позволил мне обнаружить в irb то, о чем вы не упоминали: «RuntimeError
[1, 2] Да. [3] не уверен ... [4] Когда я кодирую в своем самом профессиональном, я склонен создавать собственные типы ошибок, которые наследуются от «StandardError». Это не должно быть сложнее, чем несколько строк, например 'class MissingArgumentsError
Очень информативно, но в каких ситуациях вы захотите выбросить исключение, а не ошибку времени выполнения, если ошибка времени выполнения предпочтительна для написания либрана? –