CA2202, comment résoudre cette affaire
Quelqu'un peut-il me dire comment supprimer tous les CA2202 avertissements à partir 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.Utilisation : l'Objet "cryptoStream' peuvent être éliminés plus d'une fois dans la méthode 'CryptoServices.Chiffrer(string, byte[], byte[])'. Pour éviter de générer un Système.ObjectDisposedException vous ne devriez pas appeler dispose de plus d'une heure sur un objet.: Lignes: 34
Avertissement 8 CA2202 : Microsoft.Utilisation : l'Objet "memoryStream' peuvent être éliminés plus d'une fois dans la méthode 'CryptoServices.Chiffrer(string, byte[], byte[])'. Pour éviter de générer un Système.ObjectDisposedException vous ne devriez pas appeler dispose de plus d'une heure sur un objet.: Lignes: 34, 37
Vous avez besoin de Visual Studio Analyse du Code pour voir ces mises en garde (ce ne sont pas de compilateur c# mises en garde).
- Ce code ne génère pas ces mises en garde.
- Je reçois des avertissements 0 pour cette (Warn niveau 4, VS2010). Et pour quelqu'un googler problèmes dans ce domaine, des moyens d'ajouter le texte, les avertissements ainsi.
- CAxxxx avertissements sont générés par Analyse de Code et FxCop.
- Cet avertissement ne s'applique pas à l'montré code -- avertissements peuvent être supprimées pour ce scénario. Une fois que vous avez examiné votre code et d'accord avec cette évaluation, la place au-dessus de votre méthode: "
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification="BrainSlugs83 said so.")]
" -- assurez-vous d'avoir un "using System.Diagnostics.CodeAnalysis;
" déclaration de l'usage de votre bloc. - Regardez: msdn.microsoft.com/en-us/library/...
Vous devez vous connecter pour publier un commentaire.
Cette compile sans warning:
Modifier en réponse aux commentaires:
Je viens de vérifié encore une fois que ce code ne génère pas de l'avertissement, alors que l'original n'.
Dans le code d'origine,
CryptoStream.Dispose()
etMemoryStream().Dispose(
) sont en fait appelé deux fois (ce qui peut ou peut ne pas être un problème).Le code modifié comme suit: les références sont mis à
null
, dès que la responsabilité de l'élimination est transféré à un autre objet. E. g.memoryStream
est fixé ànull
après l'appel àCryptoStream
constructeur a réussi.cryptoStream
est fixé ànull
, après l'appel àStreamWriter
constructeur a réussi. Si aucune exception ne se produit,streamWriter
est disposé dans lefinally
bloc, et va à son tour jeterCryptoStream
etMemoryStream
.cryptoStream
est disposé dans le enfin-bloc, cela signifie que la lignecryptoStream = new ...
réussi.memoryStream
est fixé ànull
après que, si c'est pas éliminés avant de les jeter cryptoStream.Vous devez supprimer les avertissements dans ce cas. Code qui traite avec de la vaisselle jetable doit être constante, et vous ne devriez pas avoir de soins que les autres classes, prendre possession de l'jetables que vous avez créé et aussi appel
Dispose
sur eux.Mise à JOUR: Dans le IDisposable.Disposer de la documentation, vous pouvez lire ceci:
Il peut être soutenu que cette règle existe afin que les développeurs peuvent utiliser le
using
déclaration sainement dans une cascade de consommables, comme je l'ai montré ci-dessus (ou peut-être que c'est juste un joli effet de bord). Par la même occasion, puis, CA2202 ne sert à rien, et il devrait être supprimé du projet-sage. Le véritable coupable serait une mauvaise mise en œuvre deDispose
, et CA1065 doit prendre soin de cela (si c'est sous votre responsabilité).Bien, il est précis, la méthode dispose() sur ces cours d'eau sera appelé plus d'une fois. La classe StreamReader prendra la "propriété" de la cryptoStream donc l'élimination streamWriter permettra également de disposer cryptoStream. De même, la classe CryptoStream en prend la responsabilité de la memoryStream.
Ce ne sont pas exactement les bugs réels, ces .NET les classes sont résistants à de multiples Dispose() appels. Mais si vous voulez vous débarrasser de l'avertissement alors vous devez supprimer l'instruction à l'aide de ces objets. Et la douleur vous-même un peu de raisonnement ce qui va se passer si le code génère une exception. Ou fermer le message d'avertissement avec un attribut. Ou tout simplement les ignorer l'avertissement, car il est stupide.
using
états doit le rester. Ces avertissements sont vraiment stupides.using
consolidés. Il se sent juste mal à compter sur un autre objet pour se défaire d'un objet que j'ai créé. Pour ce code, c'est OK, mais il y a de nombreuses implémentations deStream
etTextWriter
là (pas seulement sur la BCL). Le code à utiliser toutes les doit être cohérente.using
et de commentaire, un lien vers cette page.XmlDocument.Save()
méthode appelleDispose
fourni sur le paramètre? je ne le vois pas dans la documentation deSave(XmlWriter)
(où je suis en train de vivre la FxCop bug), ou dans leSave()
de la méthode elle-même, ou dans la documentation deXmlDocument
lui-même.Lorsqu'un StreamWriter est éliminé, il sera automatiquement disposer le enveloppés Flux (ici: la CryptoStream). CryptoStream également automatiquement dispose la enveloppé Flux (ici: la MemoryStream).
De sorte que votre MemoryStream est disposé à la fois par la CryptoStream et la à l'aide de déclaration. Et votre CryptoStream est éliminé par le StreamWriter et l'extérieur à l'aide de déclaration.
Après une période d'expérimentation, il semble être impossible de se débarrasser des avertissements. Theorectically, MemoryStream doit être éliminée, mais alors vous, théoriquement, ne pouvait pas accéder à sa méthode ToArray plus. Pratiquement, un MemoryStream n'a pas besoin d'être éliminés, alors j'aimerais aller avec cette solution et de supprimer la CA2000 avertissement.
Je voudrais faire cela à l'aide de
#pragma warning disable
.L' .NET Framework lignes Directrices recommandent de mettre en œuvre IDisposable.Disposer d'une telle manière qu'elle peut être appelée plusieurs fois. De la MSDN description de IDisposable.Disposer:
Donc la mise en garde semble être presque dénuée de sens:
Je suppose qu'il pourrait être soutenu que l'avertissement peut être utile si vous utilisez un mal mis en œuvre IDisposable objet qui ne respecte pas les normes de mise en œuvre des lignes directrices. Mais lors de l'utilisation de classes à partir de la .NET Framework comme vous le faites, je dirais qu'il est sûr de supprimer l'avertissement à l'aide d'un #pragma. Et à mon avis c'est préférable de passer à travers des cerceaux comme proposé dans la documentation MSDN pour cette mise en garde.
#pragma warning disable
ne peut être utilisé pour supprimer les avertissements du compilateur. Pour supprimer un Code d'avertissement d'Analyse, vous devez utiliser un attribut.J'ai été confronté à des problèmes similaires dans mon code.
Ressemble à l'ensemble CA2202 chose est déclenchée car
MemoryStream
peuvent être éliminés si une exception se produit dans le constructeur (CA2000).Cela pourrait être résolu comme ceci:
Avis que nous devons retourner le
memoryStream
l'intérieur de la dernièreusing
déclaration (ligne 10) parce quecryptoStream
obtient disposé, à la ligne 11 (parce qu'il est utilisé dansstreamWriter
using
déclaration), ce qui conduitmemoryStream
pour obtenir également cédé à la ligne 11 (parce quememoryStream
est utilisé pour créer lecryptoStream
).Au moins ce code a fonctionné pour moi.
EDIT:
Drôle que cela puisse paraître, j'ai découvert que si vous remplacez la
GetMemoryStream
méthode avec le code suivant,vous obtenez le même résultat.
La cryptostream est basé sur le memorystream.
Ce qui semble se passer, c'est que lorsque le crypostream est éliminé à la fin de l'aide) memorystream est également disposée, alors memorystream est disposé de nouveau.
Je voulais résoudre ce la bonne manière - c'est sans supprimer les avertissements et à juste titre, l'élimination de tous les objets jetables.
J'ai sorti 2 des 3 cours d'eau comme les champs et éliminés dans le
Dispose()
méthode de ma classe. Oui, la mise en œuvre de laIDisposable
interface ne serait pas forcément ce que vous cherchez, mais la solution semble assez propre que par rapport àdispose()
des appels de tous des endroits aléatoires dans le code.Hors-sujet, mais je vous suggère d'utiliser une autre technique de formatage pour le groupement des
using
s:J'ai aussi l'avocat à l'aide de
var
s ici afin d'éviter les répétitions de très longue noms de classe.P. S. Merci à @ShellShock pour souligner que je ne peux pas omettre les accolades pour les premières
using
, car il seraitmemoryStream
dansreturn
énoncé de la portée.if
s (si je ne les conseils de cette technique pour autre chose queusing
s).return
déclaration. Tellement vrai. J'ai édité la réponse pour en tenir compte.using
sans accolades rend le code plus fragiles (pensez à des années de diffs et les fusions). joelonsoftware.com/2005/05/11/making-wrong-code-look-wrong & imperialviolet.org/2014/02/22/applebug.htmlÉviter tout usage et de l'utilisation imbriquée Jetez-Appels!
using
dans ce cas.Je voulais juste déballer le code de sorte que nous pouvons voir plusieurs appels à
Dispose
sur les objets:Alors que la plupart .NET de classe sont (je l'espère) très résistant contre l'erreur de multiples appels à
.Dispose
, pas tous classes sont défensive contre programmeur abus.FX Cop sait cela, et vous avertit.
Vous avez un peu de choix;
Dispose
une fois sur n'importe quel objet, n'utilisez pasusing
J'ai utilisé ce genre de code qui prend byte[] et retour byte[] sans l'aide de flux de
De cette façon, tout ce que vous avez à faire est de conversion de la chaîne de byte[] à l'aide de codages.