代码分析 - 不要多次丢弃对象

时间:2012-02-02 09:54:16

标签: c# code-analysis

我已尝试遵循此方法的代码分析规则:

public static string Encrypt(string password)
{
    string myPassword = string.Empty;
    if (!string.IsNullOrEmpty(password))
    {
        myPassword = password;
        byte[] Value = System.Text.Encoding.UTF8.GetBytes(myPassword);
        SymmetricAlgorithm mCSP = new RijndaelManaged();
        mCSP.Key = _key;
        mCSP.IV = _initVector;
        using (ICryptoTransform ct = mCSP.CreateEncryptor(mCSP.Key, mCSP.IV))
        {
            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write))
                {
                    cs.Write(Value, 0, Value.Length);
                    cs.FlushFinalBlock();
                    cs.Close();
                    myPassword = Convert.ToBase64String(ms.ToArray());
                }
            }
        }
    }
    return myPassword;
}

添加了所有Try {} Finaly{}块,但它仍在向我大喊我不尊重规则2202。 有人可以帮我一把吗?

是的,我已阅读有关此主题的其他帖子并尝试应用它, 但最后我仍然得到同样的信息。

4 个答案:

答案 0 :(得分:13)

要删除cs的CA2202警告,只需删除对其Close方法的调用。

ms的CA2202问题有点复杂。警告正在出现,因为CryptoStream可以通过构造函数来处理它收到的流,这意味着对ms.Close()的一个不恰当的调用是你无法避免的。好消息是,这种不合时宜的性格在你的情况下没有任何副作用,同样适用于双重处置,所以你可以安全地拍打SuppressMessageAttribute并忽略问题。 (对于你实际上需要传递流以通过类似CryptoStream之类的不可避免的处置来生存的情况,通常的技术是使用流子类,其实例化代码可以防止其处置。)

答案 1 :(得分:2)

摆脱这两行,不需要它们:

cs.FlushFinalBlock();
cs.Close();

答案 2 :(得分:2)

documentation on this topic之后应该导致此代码:

public static string Encrypt(string password)
{
    string myPassword = string.Empty;
    if (!string.IsNullOrEmpty(password))
    {
        myPassword = password;
        byte[] Value = System.Text.Encoding.UTF8.GetBytes(myPassword);
        SymmetricAlgorithm mCSP = new RijndaelManaged();
        mCSP.Key = _key;
        mCSP.IV = _initVector;
        using (ICryptoTransform ct = mCSP.CreateEncryptor(mCSP.Key, mCSP.IV))
        {
            System.IO.MemoryStream ms = null;
            try
            {
                ms = new System.IO.MemoryStream()
                var tmp = ms;
                using (CryptoStream cs = new CryptoStream(ms, ct, 
                                                       CryptoStreamMode.Write))
                {
                    ms = null;

                    cs.Write(Value, 0, Value.Length);
                    cs.FlushFinalBlock();
                    cs.Close();
                    myPassword = Convert.ToBase64String(tmp.ToArray());
                }
            }
            finally
            {
                if(ms != null)
                    ms.Dispose();
            }
        }
    }
    return myPassword;
}

答案 3 :(得分:2)

关于此分析警告(http://msdn.microsoft.com/en-us/library/ms182334.aspx)的文档给出了这个示例,与您的示例类似,它正在操纵流:

Stream stream = null;
try
{
    stream = new FileStream("file.txt", FileMode.OpenOrCreate);
    using (StreamWriter writer = new StreamWriter(stream))
    {
        stream = null;
        // Use the writer object...
    }
}
finally
{
    if(stream != null)
        stream.Dispose();
}

但这仍然给出了错误。以下将解决错误:

Stream stream = null;
StreamWriter writer = null;
try
{
   stream = new FileStream("file.txt", FileMode.OpenOrCreate);
   writer = new StreamWriter(stream))

   // Do some stuff on the stream writer..
}
finally
{
   if(writer != null)
       writer.Dispose();
   else if(stream != null)
       stream.Dispose();
}

原因很简单;如果作者总是为你处理流。只有在没有成功创建编写器的情况下,才应自行处理流。但我必须承认我更喜欢以下语法,如果你创建一个MemoryStream而不是FileStream,发生异常的可能性很小,我宁愿抑制CA.请注意,您可以使用语句进行堆叠,因此通常不需要额外的“嵌套级别”。

using (Stream stream = new FileStream("file.txt", FileMode.OpenOrCreate))
using (StreamWriter writer = new StreamWriter(stream))
{
    // Use the writer object...
}