Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct IDisposable implementation for this code

I have the following code

public static byte[] Compress(byte[] CompressMe)
{
    using (MemoryStream ms = new MemoryStream())
    {
        using (GZipStream gz = new GZipStream(ms, CompressionMode.Compress,true))
        {
            gz.Write(CompressMe, 0, CompressMe.Length);
            ms.Position = 0;
            byte[] Result = new byte[ms.Length];
            ms.Read(Result, 0, (int)ms.Length);
            return Result;
        }
    }
}

This works fine, but when I run code analysis on it, it comes up with the following message

CA2202 : Microsoft.Usage : Object 'ms' can be disposed more than once in 
method 'Compression.Compress(byte[])'. To avoid generating a 
System.ObjectDisposedException you should not call Dispose more than one 
time on an object.

As far as I'm concerned, when the GZipStream is Disposed, it leaves the underlying Stream (ms) open, due to the last parameter of the constructor (leaveOpen=true).

If I change my code slightly.. remove the 'using' block around the MemoryStream and change the 'leaveOpen' parameter to false..

public static byte[] Compress(byte[] CompressMe)
{
    MemoryStream ms = new MemoryStream();
    using (GZipStream gz = new GZipStream(ms, CompressionMode.Compress, false))
    {
        gz.Write(CompressMe, 0, CompressMe.Length);
        ms.Position = 0;
        byte[] Result = new byte[ms.Length];
        ms.Read(Result, 0, (int)ms.Length);
        return Result;
    }
}

This then comes up with..

CA2000 : Microsoft.Reliability : In method 'Compression.Compress(byte[])',
object 'ms' is not disposed along all exception paths. Call 
System.IDisposable.Dispose on object 'ms' before all references to 
it are out of scope.

I can't win.. (unless I'm missing something obvious) I've tried various things, like putting a try/finally around the block, and Disposing of the MemoryStream in there, but it either says that I'm disposing of it twice, or not at all !!

like image 860
Rich S Avatar asked Nov 18 '11 12:11

Rich S


People also ask

How do you implement IDisposable?

Make sure that Dispose(bool) is declared as protected, virtual, and unsealed. Modify Dispose() so that it calls Dispose(true), then calls SuppressFinalize on the current object instance ( this , or Me in Visual Basic), and then returns. Modify your finalizer so that it calls Dispose(false) and then returns.

What does it mean when an object implements IDisposable?

Typically, types that use unmanaged resources implement the IDisposable or IAsyncDisposable interface to allow the unmanaged resources to be reclaimed. When you finish using an object that implements IDisposable, you call the object's Dispose or DisposeAsync implementation to explicitly perform cleanup.

What is IDisposable in C #?

IDisposable is an interface defined in the System namespace. It is used to release managed and unmanaged resources. Implementing IDisposable interface compels us to implement 2 methods and 1 boolean variable – Public Dispose() : This method will be called by the consumer of the object when resources are to be released.

Why should we implement IDisposable?

in a class, you should implement IDisposable and overwrite the Dispose method to allow you to control when the memory is freed. If not, this responsibility is left to the garbage collector to free the memory when the object containing the unmanaged resources is finalized.


1 Answers

Apart from the disposing issue, your code is also broken. You should close the zip stream before reading back the data.

Also there is already a ToArray() method on MemoryStream, no need to implement that yourself.

using (MemoryStream ms = new MemoryStream())
{
    using (GZipStream gz = new GZipStream(ms, CompressionMode.Compress,true))
    {
        gz.Write(CompressMe, 0, CompressMe.Length);
    }
    return ms.ToArray();
}

I'd simply suppress the warning, since it's a false positive. Code analysis is there to serve you, not the other way round.

like image 121
CodesInChaos Avatar answered Nov 09 '22 06:11

CodesInChaos