web-dev-qa-db-fra.com

MemoryStream.Close () ou MemoryStream.Dispose ()

Lequel dois-je appeler?

Est-il nécessaire d'appeler les deux?

L'autre jettera-t-il une exception si j'ai déjà appelé l'un d'eux?

47
ashwnacharya

Close() et Dispose(), lorsqu'elles sont appelées sur un MemoryStream, servent uniquement à faire deux choses:

  • Marquez l’objet éliminé de sorte que toute utilisation accidentelle future de l’objet lève une exception.
  • Peut-être1 libérez les références aux objets gérés, ce qui peut faciliter le travail du CPG en fonction de son implémentation (Sur les algorithmes GC actuels, cela ne fait aucune différence. C'est donc un sujet de discussion universitaire qui n'a pas d'impact significatif sur le monde réel.)

MemoryStream ne dispose d'aucune ressource non gérée, vous ne devez donc techniquement pas en disposer. Le fait de ne pas supprimer un MemoryStream équivaut approximativement à supprimer une référence à un byte[] - le CPG les nettoiera de la même manière.

Lequel dois-je appeler? Est-il nécessaire d'appeler les deux?

La méthode Dispose() des flux déléguer directement à la méthode Close()2, donc les deux font exactement la même chose.

L'autre jettera-t-il une exception si j'ai déjà appelé l'un d'eux?

La documentation pour IDisposable.Dispose() indique spécifiquement qu'il est prudent d'appeler Dispose() plusieurs fois, quel que soit l'objet.3. (Si ce n'est pas le cas pour une classe particulière, cette classe implémente l'interface IDisposable d'une manière non conforme à son contrat, ce qui constituerait un bogue.)

Tout cela pour dire: que vous disposiez ou non d'un MemoryStream ne fait pas une grande différence. La seule vraie raison pour laquelle il utilise les méthodes CloseDispose est qu’elle hérite de Stream, qui requiert ces méthodes dans le cadre de son contrat pour la prise en charge des flux qui _/do disposent de ressources non gérées (telles que des descripteurs de fichier ou de socket).


1 Mise en œuvre de Mono ne libère pas la référence byte[]. Je ne sais pas si l'implémentation de Microsoft fait.

2 "Cette méthode appelle Close, qui appelle ensuite Stream.Dispose (Boolean)."

3 "Si la méthode Dispose d'un objet est appelée plusieurs fois, il doit ignorer tous les appels après le premier."

92
cdhowie

Utilisez le bloc using pour que votre objet soit supprimé si son implémente l'interface IDisposable

7
TalentTuner

Vous pouvez utiliser le bloc using pour cela. Il appellera automatiquement Dispose quand il sortira de sa portée.

Exemple:

using (MemoryStream ms = new MemoryStream())
{
    // Do something with ms..
}
// ms is disposed here

J'espère que cela a aidé.

6
Kevin

le code suivant est Stream.Dispose à partir de réflecteur, comme vous pouvez le constater, vous n'avez pas besoin de fermer si vous en disposez (ce qui est implicite lorsque vous utilisez)

public void Dispose()
{
    this.Close();
}
4
vc 74

Lequel dois-je appeler?

N'importe lequel d'entre eux.

Est-il nécessaire d'appeler les deux?

Non, l'un ou l'autre suffit.

L'autre jettera-t-il une exception si j'ai déjà appelé l'un d'eux?

Non, le modèle jetable déclare que les appels ultérieurs à Dispose ne causent pas d'effets négatifs.

4
QrystaL

L'appel de Close () appellera en interne Dispose () pour libérer les ressources.

Voir ce lien pour plus d’informations: msdn

3
Hps

Appeler uniquement Dispose() fera l'affaire =)

1
Singleton

Dans .NET 3.5 (n’a pas vérifié les autres versions), les méthodes sont appelées dans l’ordre suivant lors de la mise au rebut d’un MemoryStream:

  1. Stream.Dispose ()
    • appelle simplement Close
  2. Stream.Close ()
    • appelle Dispose (true), puis GC.SuppressFinalize (this)
  3. MemoryStream.Dispose (true)
    • définit les indicateurs _isOpen, _writable et _expandable sur false
  4. Stream.Dispose (true)
    • ferme l'événement async si actif
1
Tor Langlo

En tant que première solution, il est recommandé d'utiliser des instructions using chaque fois que possible. Ceci est décrit ici: http://msdn.Microsoft.com/en-us/library/yh598w02.aspx

Lorsque la durée de vie d'un objet IDisposable est limitée à une seule méthode, vous devez le déclarer et l'instancier dans l'instruction using. L'instruction using appelle la méthode Dispose de la manière appropriée sur l'objet, et (lorsque vous l'utilisez comme indiqué précédemment), l'objet lui-même devient hors de portée dès l'appel de Dispose. Dans le bloc using, l'objet est en lecture seule et ne peut pas être modifié ni réaffecté.

Pour en venir maintenant à la question, comme d'autres l'ont suggéré dans la plupart des classes du framework .NET, il n'y a pas de différence entre Close () et Dispose () et peu importe la méthode que vous appelez. Vous devriez appeler un mais pas les deux. Cependant, il existe des exceptions.

Il y a des exceptions. Par exemple, System.Windows.Forms.Form et System.Data.SqlClient.SqlConnection ont un comportement différent pour Close () et Dispose ().

Pour plus de détails, vous pouvez vérifier ici: https://blogs.msdn.Microsoft.com/kimhamil/2008/03/15/the-often-non-difference-between-close-and-dispose/

0
sin2akshay

Aucune de ces réponses. Vous n'avez pas besoin d'appeler ni Close ni Dispose.

MemoryStream ne contient aucune ressource non gérée, la seule ressource à récupérer est donc la mémoire. La mémoire sera récupérée lors de la récupération de place avec le reste de l'objet MemoryStream lorsque votre code ne fera plus référence à la variable MemoryStream.

Si vous avez une référence de longue durée à la MemoryStream, vous pouvez définir cette référence sur null pour permettre à la MemoryStream d'être nettoyée. Close et Dispose libèrent ni le tampon Steam ni l'objet MemoryStream proprement dit.

Etant donné que ni Stream ni MemoryStream ne disposent de finaliseur, il n'est pas nécessaire d'appeler Close ou Dispose pour provoquer l'appel de GC.SuppressFinalize afin d'optimiser la récupération de place. Il n'y a pas de finaliseur à supprimer.

Les docs pour MemoryStream le dire de cette façon:

Ce type implémente l'interface IDisposable, mais ne dispose d'aucune ressource. Cela signifie que son élimination en appelant directement Dispose() ou en utilisant une construction de langage telle que using (en C #) ou Using (en Visual Basic) n'est pas nécessaire.

0
Edward Brey