Анализ кода - не выбрасывайте объект несколько раз - PullRequest
8 голосов
/ 02 февраля 2012

Я пытался следовать правилам анализа кода по этому методу:

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 ]

13 голосов
/ 02 февраля 2012

Чтобы избавиться от предупреждения CA2202 для cs, просто удалите вызов его Close метода.

Проблема CA2202 для ms немного сложнее. Предупреждение появляется, потому что у CryptoStream есть эмпронерия, чтобы распоряжаться потоком, через который он получил, конструктор, что означает, что есть один неуместный вызов ms.Close(), который вы не можете избежать. Хорошая новость заключается в том, что это несвоевременное расположение не имеет побочных эффектов в вашем случае, и то же самое относится и к двойному расположению, так что вы можете спокойно набрать SuppressMessageAttribute и проигнорировать проблему. (Для случаев, когда вам действительно нужно передать поток, чтобы пережить его непредсказуемое расположение чем-то вроде CryptoStream, обычным методом является использование подкласса потока, расположение которого может быть предотвращено его экземпляром.)

2 голосов
/ 10 октября 2012

Документация по этому предупреждению анализа (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...
}
2 голосов
/ 02 февраля 2012

Следуя документации по этой теме должен привести к этому коду:

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;
}
2 голосов
/ 02 февраля 2012

Избавьтесь от этих двух строк, они не нужны:

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