Quelqu'un peut-il me dire comment supprimer tous les avertissements CA2202 du code suivant?
public static byte[] Encrypt(string data, byte[] key, byte[] iv)
{
using(MemoryStream memoryStream = new MemoryStream())
{
using (DESCryptoServiceProvider cryptograph = new DESCryptoServiceProvider())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptograph.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
using(StreamWriter streamWriter = new StreamWriter(cryptoStream))
{
streamWriter.Write(data);
}
}
}
return memoryStream.ToArray();
}
}
Avertissement 7 CA2202: Microsoft.Usage: L'objet 'cryptoStream' peut être supprimé plusieurs fois dans la méthode 'CryptoServices.Encrypt (string, byte [], byte [])'. Pour éviter de générer une exception System.ObjectDisposedException, vous ne devez pas appeler Dispose plus d'une fois sur un objet.: Lignes: 34
Avertissement 8 CA2202: Microsoft.Usage: L'objet 'memoryStream' peut être supprimé plusieurs fois dans la méthode 'CryptoServices.Encrypt (string, byte [], byte [])'. Pour éviter de générer une exception System.ObjectDisposedException, vous ne devez pas appeler Dispose plus d'une fois sur un objet: Lignes: 34, 37
Vous avez besoin de l'analyse du code Visual Studio pour voir ces avertissements (ce ne sont pas des avertissements du compilateur c #).
la source
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification="BrainSlugs83 said so.")]
" - assurez-vous d'avoir uneusing System.Diagnostics.CodeAnalysis;
déclaration " " dans votre bloc d'utilisations.Réponses:
Cela compile sans avertissement:
Modifier en réponse aux commentaires: je viens de vérifier à nouveau que ce code ne génère pas l'avertissement, contrairement à l'original. Dans le code d'origine,
CryptoStream.Dispose()
etMemoryStream().Dispose(
) sont en fait appelés deux fois (ce qui peut ou non être un problème).Le code modifié fonctionne comme suit: les références sont définies sur
null
, dès que la responsabilité de l'élimination est transférée à un autre objet. EgmemoryStream
est mis à unenull
fois que l'appel auCryptoStream
constructeur a réussi.cryptoStream
est défini surnull
, après que l'appel auStreamWriter
constructeur a réussi. Si aucune exception ne se produit,streamWriter
est disposé dans lefinally
bloc et disposera à son tourCryptoStream
etMemoryStream
.la source
Vous devez supprimer les avertissements dans ce cas. Le code qui traite des jetables doit être cohérent et vous ne devriez pas avoir à vous soucier que d'autres classes s'approprient les jetables que vous avez créés et font également appel
Dispose
à eux.MISE À JOUR: Dans la documentation IDisposable.Dispose , vous pouvez lire ceci:
On peut soutenir que cette règle existe pour que les développeurs puissent utiliser la
using
déclaration dans une cascade de jetables, comme je l'ai montré ci-dessus (ou peut-être que c'est juste un bel effet secondaire). De la même manière, CA2202 ne sert à rien et devrait être supprimé au niveau du projet. Le vrai coupable serait une implémentation défectueuse deDispose
, et CA1065 devrait s'en occuper (si c'est sous votre responsabilité).la source
Eh bien, c'est exact, la méthode Dispose () sur ces flux sera appelée plus d'une fois. La classe StreamReader deviendra «propriétaire» du cryptoStream, donc l'élimination de streamWriter supprimera également cryptoStream. De même, la classe CryptoStream prend en charge la responsabilité de memoryStream.
Ce ne sont pas exactement de vrais bogues, ces classes .NET sont résilientes à plusieurs appels Dispose (). Mais si vous voulez vous débarrasser de l'avertissement, vous devez supprimer l'instruction using pour ces objets. Et souffrez-vous un peu en raisonnant ce qui se passera si le code lève une exception. Ou fermez l'avertissement avec un attribut. Ou ignorez simplement l'avertissement car c'est idiot.
la source
using
déclarations devraient rester. Ces avertissements sont vraiment stupides.using
déclarations. Cela me semble juste mal de s'appuyer sur un autre objet pour disposer d'un objet que j'ai créé. Pour ce code, c'est OK, mais il existe de nombreuses implémentations deStream
etTextWriter
là-bas (pas seulement sur la BCL). Le code pour les utiliser tous doit être cohérent.XmlDocument.Save()
méthode appelleraDispose
le paramètre fourni? Je ne le vois pas dans la documentation deSave(XmlWriter)
(où je rencontre le bogue FxCop), ni dans laSave()
méthode elle-même, ni dans la documentationXmlDocument
elle - même.Lorsqu'un StreamWriter est supprimé, il supprimera automatiquement le Stream encapsulé (ici: le CryptoStream ). CryptoStream supprime également automatiquement le Stream encapsulé (ici: le MemoryStream ).
Ainsi, votre MemoryStream est supprimé à la fois par CryptoStream et l' instruction using . Et votre CryptoStream est supprimé par le StreamWriter et l' instruction using externe .
Après quelques expérimentations, il semble impossible de se débarrasser complètement des avertissements. Théoriquement, le MemoryStream doit être supprimé, mais vous ne pourriez théoriquement plus accéder à sa méthode ToArray. Pratiquement, un MemoryStream n'a pas besoin d'être éliminé, alors j'irais avec cette solution et supprimerais l'avertissement CA2000.
la source
Je ferais cela en utilisant
#pragma warning disable
.Les directives du .NET Framework recommandent d'implémenter IDisposable.Dispose de telle sorte qu'il puisse être appelé plusieurs fois. À partir de la description MSDN de IDisposable .
Par conséquent, l'avertissement semble presque dénué de sens:
Je suppose que l'on pourrait faire valoir que l'avertissement peut être utile si vous utilisez un objet IDisposable mal implémenté qui ne suit pas les directives d'implémentation standard. Mais lorsque vous utilisez des classes du .NET Framework comme vous le faites, je dirais qu'il est prudent de supprimer l'avertissement en utilisant un #pragma. Et à mon humble avis, c'est préférable de passer par des cerceaux comme suggéré dans la documentation MSDN pour cet avertissement .
la source
#pragma warning disable
ne peut être utilisé que pour supprimer les avertissements du compilateur. Pour supprimer un avertissement d'analyse de code, vous devez utiliser un attribut.J'ai été confronté à des problèmes similaires dans mon code.
On dirait que toute la chose CA2202 est déclenchée car elle
MemoryStream
peut être supprimée si une exception se produit dans le constructeur (CA2000).Cela pourrait être résolu comme ceci:
Notez que nous devons renvoyer l'
memoryStream
intérieur de la dernièreusing
instruction (ligne 10) car ilcryptoStream
est supprimé à la ligne 11 (car il est utilisé dans l'streamWriter
using
instruction), ce qui conduitmemoryStream
à être également supprimé à la ligne 11 (car ilmemoryStream
est utilisé pour créer lecryptoStream
).Au moins ce code a fonctionné pour moi.
ÉDITER:
Aussi drôle que cela puisse paraître, j'ai découvert que si vous remplacez la
GetMemoryStream
méthode par le code suivant,vous obtenez le même résultat.
la source
Le cryptostream est basé sur le memorystream.
Ce qui semble se produire, c'est que lorsque le flux cryogénique est disposé (à la fin de l'utilisation), le flux mémoire est également supprimé, puis le flux mémoire est à nouveau supprimé.
la source
Je voulais résoudre ce problème de la bonne manière - c'est-à-dire sans supprimer les avertissements et éliminer correctement tous les objets jetables.
J'ai extrait 2 des 3 flux en tant que champs et les
Dispose()
ai disposés dans la méthode de ma classe. Oui, la mise en œuvre de l'IDisposable
interface n'est peut-être pas nécessairement ce que vous recherchez, mais la solution semble assez propre par rapport auxdispose()
appels provenant de tous les endroits aléatoires du code.la source
Hors sujet mais je vous suggère d'utiliser une technique de mise en forme différente pour le regroupement des
using
s:Je recommande également d'utiliser
var
s ici pour éviter les répétitions de noms de classe très longs.PS Merci à @ShellShock pour remarquer que je ne peux pas accolades Omettre pour le premier
using
comme il seraitmemoryStream
dans lareturn
déclaration sur la portée.la source
if
s (bien que je ne conseille pas cette technique pour autre chose queusing
s).return
déclaration. Tellement vrai. J'ai modifié la réponse pour refléter cela.using
Personnellement, je pense que le sans accolades rend le code plus fragile (pensez à des années de différences et de fusions). joelonsoftware.com/2005/05/11/making-wrong-code-look-wrong & imperialviolet.org/2014/02/22/applebug.htmlÉvitez toutes les utilisations et utilisez des appels de suppression imbriqués!
la source
using
dans ce cas.Je voulais juste déballer le code afin que nous puissions voir plusieurs appels
Dispose
sur les objets:Alors que la plupart des classes .NET sont (espérons-le) résilientes contre l'erreur de plusieurs appels à
.Dispose
, toutes les classes ne sont pas aussi défensives contre une mauvaise utilisation des programmeurs.FX Cop le sait et vous en avertit.
Vous avez quelques choix;
Dispose
qu'une seule fois sur n'importe quel objet; ne pas utiliserusing
la source
J'ai utilisé ce genre de code qui prend l'octet [] et renvoie l'octet [] sans utiliser de flux
De cette façon, tout ce que vous avez à faire est de convertir une chaîne en octet [] en utilisant des encodages.
la source