J'ai le code suivant
using(MemoryStream ms = new MemoryStream())
{
//code
return 0;
}
La dispose()
méthode est appelée à la fin des using
accolades, }
non? Puisque j'ai return
avant la fin de la using
déclaration, l' MemoryStream
objet sera-t-il éliminé correctement? Que se passe t-il ici?
Réponses:
Oui,
Dispose
sera appelé. Il est appelé dès que l'exécution quitte la portée duusing
bloc, quels que soient les moyens nécessaires pour quitter le bloc, que ce soit la fin de l'exécution du bloc, unereturn
instruction ou une exception.Comme @Noldorin le souligne correctement, l'utilisation d'un
using
bloc dans le code est compilée danstry
/finally
, avecDispose
un appel dans lefinally
bloc. Par exemple le code suivant:devient effectivement:
Ainsi, parce qu'il
finally
est garanti de s'exécuter après latry
fin de l'exécution du bloc, quel que soit son chemin d'exécution, ilDispose
est garanti d'être appelé, quoi qu'il arrive.Pour plus d'informations, consultez cet article MSDN .
Addendum:
Juste une petite mise en garde à ajouter: car il
Dispose
est garanti d'être appelé, c'est presque toujours une bonne idée de s'assurer queDispose
ne lève jamais d'exception lorsque vous implémentezIDisposable
. Malheureusement, il y a des classes dans la bibliothèque de base qui font un jet dans certaines circonstances , lorsque l'Dispose
on appelle - je vous regarde, WCF Service de référence / Client Proxy! - et lorsque cela se produit, il peut être très difficile de retrouver l'exception d'origine si elle aDispose
été appelée lors d'un déroulement de pile d'exceptions, puisque l'exception d'origine est avalée au profit de la nouvelle exception générée par l'Dispose
appel. Cela peut être extrêmement frustrant. Ou est-ce frustrant? Un des deux. Peut-être les deux.la source
Dispose
finalement, donc cela fonctionne efficacement sur l'implémentation definally
, comme vous le décrivez.using
Les instructions se comportent exactement comme destry ... finally
blocs, donc s'exécuteront toujours sur tous les chemins de sortie de code. Cependant, je crois qu'ils sont soumis aux très rares et rares situations dans lesquelles lesfinally
blocs ne sont pas appelés. Un exemple dont je me souviens est si le thread de premier plan se termine alors que les threads d'arrière-plan sont actifs: tous les threads en dehors du GC sont mis en pause, ce qui signifie que lesfinally
blocs ne sont pas exécutés.Edition évidente: ils se comportent de la même manière en dehors de la logique qui leur permet de gérer les objets IDisposables, d'oh.
Contenu bonus: ils peuvent être empilés (là où les types diffèrent):
Et aussi délimité par des virgules (où les types sont les mêmes):
la source
Votre objet MemoryStream sera supprimé correctement, pas besoin de vous en soucier.
la source
Avec l'
using
instruction, l'objet sera supprimé quel que soit le chemin d'achèvement.Lectures complémentaires ...
la source
Jetez un œil à votre code dans Reflector après l'avoir compilé. Vous constaterez que le compilateur refactorise le code pour s'assurer que dispose est appelé sur le flux.
la source