Quelle est la différence - technique, philosophique, conceptuelle ou autre - entre
raise "foo"
et
raise Exception.new("foo")
?
la source
Quelle est la différence - technique, philosophique, conceptuelle ou autre - entre
raise "foo"
et
raise Exception.new("foo")
?
Techniquement, le premier déclenche une RuntimeError avec le message défini sur "foo"
, et le second déclenche une exception avec le message défini sur "foo"
.
En pratique, il existe une différence significative entre le moment où vous voudriez utiliser le premier et le moment où vous souhaitez utiliser le second.
En termes simples, vous voulez probablement pas un RuntimeError
fichier Exception
. Un bloc de secours sans argument attrapera RuntimeErrors
, mais n'attrapera PAS Exception
s. Donc, si vous augmentez un Exception
dans votre code, ce code ne l'attrapera pas:
begin
rescue
end
Pour attraper le, Exception
vous devrez faire ceci:
begin
rescue Exception
end
Cela signifie qu'en un sens, an Exception
est une erreur "pire" que a RuntimeError
, car vous devez faire plus de travail pour vous en remettre.
Donc, ce que vous voulez dépend de la façon dont votre projet gère ses erreurs. Par exemple, dans nos démons, la boucle principale a un sauvetage vide qui les attrapera RuntimeErrors
, les rapportera, puis continuera. Mais dans une ou deux circonstances, nous voulons que le démon meure vraiment en cas d'erreur, et dans ce cas, nous lançons un Exception
, qui passe directement par notre "code normal de gestion des erreurs" et sort.
Et encore une fois, si vous écrivez du code de bibliothèque, vous voulez probablement un RuntimeError
, pas un Exception
, car les utilisateurs de votre bibliothèque seront surpris si cela génère des erreurs qu'un rescue
bloc vide ne peut pas détecter , et il leur faudra un moment pour comprendre pourquoi.
Enfin, je dois dire que le RuntimeError
est une sous-classe de la StandardError
classe, et la règle actuelle est que même si vous pouvez utiliser raise
n'importe quel type d'objet, le blanc rescue
ne capturera par défaut que tout ce qui hérite de StandardError
. Tout le reste doit être spécifique.
RuntimeError < StandardError < Exception
[2] Par conséquent, ce deuxième bloc de code va attraper à la fois une exception et un RuntimeError [3] il est intéressant / étrange que la relance et le sauvetage "nus" fonctionnent avec cette exception particulière [4]. La règle de base est peut-être d'élever RuntimeError dans le code client, mais de lever et de sauver ses propres exceptions personnalisées dans son propre code?StandardError
. Cela n'a pas à être plus compliqué que quelques lignes commeclass MissingArgumentsError < StandardError; end
.De la documentation officielle:
Sans argument, lève l'exception
$!
ou déclenche unRuntimeError
if$!
est nul. Avec un seulString
argument, il déclenche unRuntimeError
avec la chaîne comme message. Sinon, le premier paramètre doit être le nom d'uneException
classe (ou d'un objet qui renvoie uneException
exception lors de l'envoi). Le deuxième paramètre facultatif définit le message associé à l'exception et le troisième paramètre est un tableau d'informations de rappel. Les exceptions sont capturées par la clause de sauvetage desbegin...end
blocs.la source