Qual è la differenza - tecnica, filosofica, concettuale o altro - tra
raise "foo"
e
raise Exception.new("foo")
?
Qual è la differenza - tecnica, filosofica, concettuale o altro - tra
raise "foo"
e
raise Exception.new("foo")
?
Risposte:
Tecnicamente, il primo solleva un'eccezione RuntimeError con il messaggio impostato su "foo"
e il secondo solleva un'eccezione con il messaggio impostato su "foo"
.
In pratica, c'è una differenza significativa tra quando si desidera utilizzare il primo e quando si desidera utilizzare il secondo.
In poche parole, probabilmente vuoi un RuntimeError
non un file Exception
. Un blocco di salvataggio senza argomento catturerà RuntimeErrors
, ma NON catturerà Exception
s. Quindi, se sollevi un Exception
nel tuo codice, questo codice non lo catturerà:
begin
rescue
end
Per catturare il Exception
dovrai fare questo:
begin
rescue Exception
end
Ciò significa che in un certo senso an Exception
è un errore "peggiore" di a RuntimeError
, perché devi fare più lavoro per risolverlo.
Quindi ciò che vuoi dipende da come il tuo progetto gestisce gli errori. Ad esempio, nei nostri daemon, il ciclo principale ha un salvataggio vuoto che li catturerà RuntimeErrors
, li segnalerà e quindi continuerà. Ma in una o due circostanze, vogliamo che il demone muoia davvero in caso di errore, e in quel caso solleviamo un Exception
, che passa direttamente attraverso il nostro "normale codice di gestione degli errori" ed esce.
E ancora, se stai scrivendo il codice di una libreria, probabilmente ne vuoi una RuntimeError
, non una Exception
, poiché gli utenti della tua libreria saranno sorpresi se solleva errori che un rescue
blocco vuoto non può rilevare, e ci vorrà un momento per capire il motivo.
Infine, dovrei dire che RuntimeError
è una sottoclasse della StandardError
classe e la regola effettiva è che sebbene sia possibile raise
qualsiasi tipo di oggetto, lo spazio vuoto rescue
per impostazione predefinita cattura solo tutto ciò che eredita StandardError
. Tutto il resto deve essere specifico.
StandardError
. Non deve essere più complicato di poche righe come class MissingArgumentsError < StandardError; end
.
Dalla documentazione ufficiale:
raise
raise( string )
raise( exception [, string [, array ] ] )
Senza argomenti, solleva l'eccezione $!
o solleva un RuntimeError
se $!
è nullo. Con un singolo String
argomento, solleva un RuntimeError
con la stringa come messaggio. Altrimenti, il primo parametro dovrebbe essere il nome di una Exception
classe (o un oggetto che restituisce Exception
un'eccezione quando viene inviata). Il secondo parametro facoltativo imposta il messaggio associato all'eccezione e il terzo parametro è una matrice di informazioni di callback. Le eccezioni sono catturate dalla clausola di salvataggio dei begin...end
blocchi.
raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
RuntimeError < StandardError < Exception
[2], pertanto, che il secondo blocco di codice sarà catturare sia un'eccezione e un RuntimeError [3] è interessante / strano che il rilancio e il salvataggio "nudi" funzionino con quella particolare eccezione [4] forse la regola pratica è aumentare RuntimeError al codice client, ma sollevare e salvare le proprie eccezioni personalizzate all'interno del proprio codice?