当有两个嵌套的using子句时,Microsoft.usage警告

时间:2012-06-29 19:17:54

标签: c#

我想知道为什么Visual Studio代码分析会用这一小段代码发出警告:

byte[] data = File.ReadAllBytes("myImage.png");
using (MemoryStream mem = new MemoryStream(data))
using (Bitmap bmp = new Bitmap(mem))            
{
     // do something with the bitmap
}

错误是:

  

对象'mem'可以在方法中多次处理...要避免   生成一个不应该调用的System.ObjectDisposedException   在物体上多次处理。

如何解决这个问题? (是的,我可以直接从文件加载位图,但在我的真实项目中,我有自己的文件格式,其中多个图像保存到一个文件中,因此我需要MemoryStream来加载来自特定范围的数据文件)

4 个答案:

答案 0 :(得分:6)

问题是Bitmap取得了它在构造函数中给出的流的所有权。 将处理流 - 您不需要。所以你需要的只是:

using (Bitmap bmp = new Bitmap(new MemoryStream(data)))            
{
     // do something with the bitmap
}

答案 1 :(得分:1)

关于第二次可靠性警告,似乎在发生这种情况时,无论您做什么,代码分析都会抱怨CA2000 CA2202。对此有多处抱怨,here's one for your enjoyment.

为了看看是否特别使用语法,我将使用扩展到try catch块并获得相同的行为。

class Program
    {
        static void Main(string[] args)
        {
            byte[] data = {};
            //using (Bitmap bitmap = new Bitmap(new MemoryStream(data)))
            //{ }

            MemoryStream mem = null;
            Bitmap bitmap = null;
            try
            {
                mem = new MemoryStream(data);
                bitmap = new Bitmap(mem);

            }
            catch (Exception)
            {

                throw;
            }
            finally
            {
                if (null!= bitmap ) bitmap.Dispose();                
                // commenting this out will provoke a CA2000.
                // uncommenting this will provoke CA2202.
                // so pick your poison.
                // if (null != mem) mem.Dispose();
            }
        } 
    }

编辑:正如你(Jaska)指出的那样,有一条来自微软的关于在Bitmap的使用块中标记内存流意图的说明:

class Program
    {
        static void Main(string[] args)
        {
            byte[] data = new byte[1000];
            MemoryStream mem = null;
            try
            {
                mem = new MemoryStream(data);
                using (Bitmap bmp = new Bitmap(mem))
                {
                    mem = null; // <-- this line will make both warning go away
                }
            }
            finally
            {
                if (mem != null)
                {
                    mem.Dispose();
                }
            } 
        } 
    }

我很高兴看到这个有效,但同时它比在位图的构造函数中使用匿名内存流有点丑陋。好吧。

答案 2 :(得分:1)

Reacher-Gilt与ms-page的链接引导我找到解决方案,这将使两个警告消失:

        byte[] data = new byte[1000];
        MemoryStream mem = null;
        try
        {
            mem = new MemoryStream(data);
            using (Bitmap bmp = new Bitmap(mem))
            {
                mem = null; // <-- this line will make both warning go away
            }
        }
        finally
        {
            if (mem != null)
            {
                mem.Dispose();
            }
        } 

答案 3 :(得分:0)

一旦你输入第二个using语句,你的Bitmap将“消耗”内存流 - 它对内存流负责,包括它的处理。这是明智的,如果你考虑一下你的用法:你是否希望在你的Bitmap构造函数中使用它之后(或期间)访问mem?我可能不会说。

答案是将两个使用语句合并在一起:using (Bitmap bitmap = new Bitmap(new MemoryStream(data)))。这应该照顾CA警告。