CA2202: не удалять объекты несколько раз

У меня такой класс...

public class Class1
{
    public Class1()
    {
        byte[] plainText = new byte[1024];
        using (MemoryStream msEncrypt = new MemoryStream())
        {
            using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            {
                csEncrypt.Write(plainText, 0, plainText.Length);
                csEncrypt.FlushFinalBlock();
                csEncrypt.Flush();
                encrypted = msEncrypt.ToArray();
            }
        }
    }
    public ICryptoTransform encryptor { get; set; }
    public byte[] encrypted { get; set; }
}

Анализ кода выдает следующее предупреждение. Не удаляйте объекты несколько раз.

http://msdn.microsoft.com/en-us/library/ms182334.aspx.

Я не могу понять эту строку в приведенной выше статье [Пример раздела]... «Вложенные операторы использования (использование в Visual Basic) могут привести к нарушению предупреждения CA2202. Если ресурс IDisposable вложенного внутреннего оператора использования содержит ресурс оператора внешнего использования метод Dispose вложенного ресурса освобождает содержащийся ресурс. Когда возникает такая ситуация, метод Dispose внешнего оператора использования пытается удалить свой ресурс во второй раз».

IL для этого кода


person Rahul Soni    schedule 07.03.2014    source источник
comment
CryptoStream может уже удалять MemoryStream.   -  person leppie    schedule 07.03.2014
comment
leppie прав, но нет ничего плохого в удалении дважды, потому что это не вызовет исключения. Ваш синтаксис правильный, и, на мой взгляд, CryptoStream не должен касаться метода Dispose внедренного потока. Я бы поспорил, чтобы подавить предупреждение.   -  person Silvermind    schedule 07.03.2014
comment
@Silvermind Я согласен с вами, это противоречит здравому смыслу. Почему я должен ожидать, что CryptoStream разместит свой базовый поток? Он может мне понадобиться для дальнейшего использования. Я считаю, что это плохой дизайн, который msft выбрал для IDisposable.   -  person Sriram Sakthivel    schedule 07.03.2014
comment
Это неплохой дизайн для IDisposable, это спорный дизайн CryptoStream. Аналогично для TextReader, BinaryReader и др.   -  person Henk Holterman    schedule 07.03.2014


Ответы (1)


В нем говорится, что когда вы вызываете Dispose для ресурса, он освобождает весь ресурс, который у него есть. Таким образом, внутренний ресурс здесь csEncrypt, который содержит внешний ресурс msEncrypt на csEncrypt.Dispose, также будет удален msEncrypt.

Позже вызывается msEncrypt.Disopse, поэтому анализ кода предупреждает вас о многократном вызове Dispose.

person Sriram Sakthivel    schedule 07.03.2014
comment
У вас неправильное распределение. csEncrypt удаляется первым и удаляет объект, на который ссылается msEncrypt. - person Damien_The_Unbeliever; 07.03.2014
comment
+1 Технически CryptoStream, похоже, вызывает только Close в обернутом потоке, а не удаляет его. Учитывая формулировку в документах, я нахожу это немного удивительным (даже если они, вероятно, делают то же самое в этом случае) - person Joachim Isaksson; 07.03.2014
comment
Спасибо за ваш ответ, Шрирам. Но почему объект может привести к удалению всех объектов, которые были ему переданы. Я даже не передаю это как ссылку. Что, если мне придется снова использовать объект во внешнем использовании? - person Rahul Soni; 07.03.2014
comment
@RahulSoni Вы не можете, вы должны осторожно использовать это в коде. Как указал Хенк в комментариях, это спорный дизайн. Если вы хотите использовать позже, вы должны утилизировать его только один раз, когда вы закончите с ним. - person Sriram Sakthivel; 07.03.2014
comment
Я проверил код в отладчике, и, как указал Иоахим, похоже, он его не утилизирует. Он просто закрывает поток. В .NET 4.5 у нас есть перегруженная версия leaveOpen, msdn.microsoft.com/en -us/library/gg712804.aspx. Будет ли еще возникать этот вопрос? - person Rahul Soni; 10.03.2014