Избавиться от CA2202

Как я могу избавиться от предупреждения CA2202 (CA2202: Microsoft.Usage: объект "compressStream" может быть размещен более одного раза в методе "Compression.InternalDecompress(byte[])". Чтобы избежать создания исключения System.ObjectDisposedException, вы не должны вызывать Избавиться от объекта более одного раза) из следующего кода:

        using (var compressedStream = new MemoryStream(inputData))
        using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
        using (var resultStream = new MemoryStream())
        {
            zipStream.CopyTo(resultStream);
            return resultStream.ToArray();
        }

Я попытался избавиться от оператора "using" и заменить его шаблоном try/finally, но затем я получил CA2000 (CA2000: Microsoft.Reliability: в методе "Compression.InternalDecompress(byte[])" вызовите System.IDisposable.Dispose на объекте 'stream' до того, как все ссылки на него выйдут из области видимости) Я попытался заменить вышеуказанный код следующим образом:

        MemoryStream decompressedData = null;
        MemoryStream stream = null;
        GZipStream decompressor = null;
        try
        {
            decompressedData = new MemoryStream();
            stream = new MemoryStream(inputData);
            decompressor = new GZipStream(stream, CompressionMode.Decompress, false);
            stream = null;

            int bytesRead = 1;
            int chunkSize = 4096;
            byte[] chunk = new byte[chunkSize];

            while ((bytesRead = decompressor.Read(chunk, 0, chunkSize)) > 0)
            {
                decompressedData.Write(chunk, 0, bytesRead);
            }

            decompressor = null;

            return decompressedData.ToArray();
        }
        finally
        {
            if (stream != null)
            {
                stream.Dispose();
            }

            if (decompressor != null)
            {
                decompressor.Dispose();
            }

            if (decompressedData != null)
            {
                decompressedData.Dispose();
            }
        }

3 ответа

Это то, что я в конечном итоге использовал - избавляется от CA2000 и CA2202:

    private static MemoryStream GetMemoryStream()
    {
        return new MemoryStream();
    }

    private static byte[] InternalDecompress(byte[] inputData)
    {
        Debug.Assert(inputData != null, "inputData cannot be null");

        MemoryStream decompressedData = GetMemoryStream();
        MemoryStream inputDataMemoryStream = GetMemoryStream();

        GZipStream decompressor = null;

        try
        {
            inputDataMemoryStream.Write(inputData, 0, inputData.Length);
            inputDataMemoryStream.Position = 0;

            decompressor = new GZipStream(inputDataMemoryStream, CompressionMode.Decompress, false);

            int bytesRead;
            int chunkSize = 4096;
            byte[] chunk = new byte[chunkSize];

            while ((bytesRead = decompressor.Read(chunk, 0, chunkSize)) > 0)
            {
                decompressedData.Write(chunk, 0, bytesRead);
            }
        }
        finally
        {
            if (decompressor != null)
            {
                decompressor.Dispose();
            }
        }

        return decompressedData.ToArray();
    }

Это то, что я использую:

public class Compression
{
    public Compression()
    {

    }

    public byte[] Compress(byte[] buffer)
    {
        byte[] gzBuffer;

        using (MemoryStream ms = new MemoryStream())
        {
            using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true))
            {
                zip.Write(buffer, 0, buffer.Length);
                zip.Close();
            }
            ms.Position = 0;

            MemoryStream outStream = new MemoryStream();

            byte[] compressed = new byte[ms.Length];
            ms.Read(compressed, 0, compressed.Length);

            gzBuffer = new byte[compressed.Length + 4];
            Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
            Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
        }

        return gzBuffer;
    }

    public byte[] Decompress(byte[] gzBuffer)
    {
        byte[] buffer;

        using (MemoryStream ms = new MemoryStream())
        {
            int msgLength = BitConverter.ToInt32(gzBuffer, 0);
            ms.Write(gzBuffer, 4, gzBuffer.Length - 4);

            buffer = new byte[msgLength];

            ms.Position = 0;
            using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
            {
                zip.Read(buffer, 0, buffer.Length);
            }
        }

        return buffer;
    }
}

Или вы можете просто добавить прагма в свой класс

#pragma warning disable 2202

namespace Your.Namespace
{
...
}

#pragma warning restore 2202

Это моя попытка. Это работает, и это избегает CA2202

    /// <summary>
    /// Compresses byte array to new byte array.
    /// </summary>
    public byte[] Compress(byte[] raw)
    {
        MemoryStream outStream = null;
        GZipStream tinyStream = null;
        byte[] retValue = null;
        try
        {
            outStream = new MemoryStream();
            tinyStream = new GZipStream(outStream, CompressionMode.Compress);
            using (var mStream = new MemoryStream(raw))
                mStream.CopyTo(tinyStream);
        }
        finally
        {
            if (tinyStream != null)
            {
                tinyStream.Dispose();
                retValue = outStream.ToArray();
            }
            else if (outStream != null)
            {
                retValue = outStream.ToArray();
                outStream.Dispose();
            }
        }
        return retValue;
    }
Другие вопросы по тегам