J'ai récemment commencé à programmer dans Ruby et je regarde la gestion des exceptions.
Je me demandais si ensure
était l'équivalent Ruby finally
en C #? Dois-je avoir:
file = File.open("myFile.txt", "w")
begin
file << "#{content} \n"
rescue
#handle the error here
ensure
file.close unless file.nil?
end
ou devrais-je faire cela?
#store the file
file = File.open("myFile.txt", "w")
begin
file << "#{content} \n"
file.close
rescue
#handle the error here
ensure
file.close unless file.nil?
end
Est- ensure
il appelé quoi qu'il arrive, même si aucune exception n'est déclenchée?
ruby-on-rails
ruby
exception
exception-handling
error-handling
Lloyd Powell
la source
la source
begin
bloc.Réponses:
Oui,
ensure
garantit que le code est toujours évalué. Voilà pourquoi ça s'appelleensure
. Donc, c'est équivalent à Java et C #finally
.Le flux général de
begin
/rescue
/else
/ensure
/end
ressemble à ceci:Vous pouvez laisser de côté
rescue
,ensure
ouelse
. Vous pouvez également laisser de côté les variables, auquel cas vous ne pourrez pas inspecter l'exception dans votre code de gestion des exceptions. (Eh bien, vous pouvez toujours utiliser la variable d'exception globale pour accéder à la dernière exception qui a été déclenchée, mais c'est un peu hacky.) Et vous pouvez laisser de côté la classe d'exception, auquel cas toutes les exceptions qui héritent deStandardError
seront interceptées. (S'il vous plaît noter que cela ne signifie pas que toutes les exceptions sont prises, car il y a des exceptions qui sont des instances deException
nonStandardError
. La plupart du temps des exceptions très graves qui compromettent l'intégrité du programme tel queSystemStackError
,NoMemoryError
,SecurityError
,NotImplementedError
,LoadError
,SyntaxError
,ScriptError
,Interrupt
,SignalException
ouSystemExit
.)Certains blocs forment des blocs d'exception implicites. Par exemple, les définitions de méthode sont implicitement aussi des blocs d'exception, donc au lieu d'écrire
tu écris juste
ou
Il en va de même pour les
class
définitions etmodule
définitions.Cependant, dans le cas spécifique que vous posez, il existe en fait un bien meilleur idiome. En général, lorsque vous travaillez avec une ressource que vous devez nettoyer à la fin, vous le faites en passant un bloc à une méthode qui fait tout le nettoyage pour vous. C'est similaire à un
using
bloc en C #, sauf que Ruby est en fait assez puissant pour que vous n'ayez pas à attendre que les grands prêtres de Microsoft descendent de la montagne et changent gracieusement leur compilateur pour vous. Dans Ruby, vous pouvez simplement l'implémenter vous-même:Et que savez-vous: c'est déjà disponible dans la bibliothèque de base en tant que
File.open
. Mais c'est un modèle général que vous pouvez également utiliser dans votre propre code, pour implémenter tout type de nettoyage de ressources (à lausing
en C #) ou de transactions ou tout ce que vous pourriez penser.Le seul cas où cela ne fonctionne pas, si l'acquisition et la libération de la ressource sont réparties sur différentes parties du programme. Mais s'il est localisé, comme dans votre exemple, vous pouvez facilement utiliser ces blocs de ressources.
BTW: en C # moderne,
using
est en fait superflu, car vous pouvez implémenter vous-même des blocs de ressources de style Ruby:la source
ensure
instructions soient exécutées en dernier, elles ne sont pas la valeur de retour.ensure
on t'appelle quoi qu'il arrive".Pour info, même si une exception est re-levée dans la
rescue
section, leensure
bloc sera exécuté avant que l'exécution du code ne continue vers le gestionnaire d'exceptions suivant. Par exemple:la source
Si vous voulez vous assurer qu'un fichier est fermé, vous devez utiliser la forme de bloc de
File.open
:la source
Oui,
ensure
est appelé en toutes circonstances. Pour plus d'informations, voir « Exceptions, Catch et Throw » du livre Programming Ruby et recherchez «sure».la source
Oui,
ensure
ASSURE qu'il est exécuté à chaque fois, vous n'avez donc pas besoin de lefile.close
dans lebegin
bloc.Au fait, une bonne façon de tester est de faire:
Vous pouvez tester pour voir si "========= intérieur assurez-vous que le bloc" sera imprimé en cas d'exception. Vous pouvez ensuite commenter l'instruction qui déclenche l'erreur et voir si l'
ensure
instruction est exécutée en voyant si quelque chose est imprimé.la source
C'est pourquoi nous avons besoin de
ensure
:la source
Oui,
ensure
commefinally
garantit que le bloc sera exécuté . Ceci est très utile pour s'assurer que les ressources critiques sont protégées, par exemple en fermant un descripteur de fichier en cas d'erreur ou en libérant un mutex.la source
File.open
partie n'est PAS dans le bloc begin-sure. Seulement,file.close
mais ce n'est pas suffisant.