摆脱CA2202

3

如何消除CA2202警告(CA2202: Microsoft.Usage:在方法“Compression.InternalDecompress(byte [])”中,对象“compressedStream”可以被处理多次。为了避免生成System.ObjectDisposedException,您不应该在一个对象上调用Dispose超过一次)从以下代码:

        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)。我已经尝试像下面这样替换上面的代码:

        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();
            }
        }

可能是CA2202,如何解决这个问题的重复。 - H H
3个回答

1

这是我使用的:

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:Microsoft.Usage:在方法'Compression.InternalDecompress(byte [])'中,对象'ms'可以被处理多次。为避免生成System.ObjectDisposedException,您不应在一个对象上调用Dispose超过一次。” - Ambuj
1
既然这只是一个警告,也许添加一个不显示警告的编译指示会有所帮助。请参见上面修改后的代码。 - Alex Mendez
我感到很烦恼的是,在2016年,这些警告(特别是CA2202)似乎完全是虚假的,并且几乎标记了所有USING语句,而实际上并没有代表可能发生的情况。 - Warren P

1

这是我最终使用的 - 可以同时解决 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();
    }

0

这是我的尝试。它可以工作并且避免了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;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接