null-conditional operator and CA2202: Do not dispose objects multiple times

568 Views Asked by At

Having the following:

StringWriter sw = null;
try
{
    sw = new StringWriter();
    using (var xw = new XmlTextWriter(sw))
    {
        doc.WriteTo(xw);
        return sw.ToString();
    }
}
finally 
{
    sw?.Dispose();
}

triggers the CA2202 (do not dispose objects multiple times) warning in Visual Studio 2015.

But the warning is not triggered if change the fianlly block to:

finally 
{
    if (sw != null)
    {
        sw.Dispose();
    }
}

Is that some strangeness of the null-conditional operator in a finally block or something, or do the analysis tools in Visual Studio simply not understand it?

EDIT: Possibly related: Why does Code Analysis flag me when using the null conditional operator with Dispose()?

2

There are 2 best solutions below

0
On

Warning 'CA2202' is correct.

'sw' should be deleted in 'xw' if 'xw' is created, or manually deleted if 'xw' fails.

So you need 'sw = null' after creating 'xw'.

StringWriter sw = null;
try
{
    sw = new StringWriter();
    using (var xw = new XmlTextWriter(sw))
    {
        sw = null; //need to set null
        doc.WriteTo(xw);
        return sw.ToString();
    }
}
finally
{
    sw?.Dispose();
}
3
On

Because you declared xw in the using block, when you exit the using block the IDisposable method for XmlTextWriter will be called. Since your string writer is only being used with the XMLWriter it will also be disposed by the garbage collector (it is an optimization to save the GC from having to rely on reference counting to determine if the object is still in use).

Edit: Further information can be found in this MSDN article.