How to fix warning CA2202?

Below is the method I am using to parse XML. It gives CA2202 code analysis warning, which says the mStream object can be deleted multiple times and I shouldn't call it more than once. How can I resolve this warning?

public static String PrintXML(String XML)
    {
        String result = "";
        string[] xmlSeperators = new string[] { "<?" };
        string[] splitResults = new string[2];

        if (!String.IsNullOrEmpty(XML))
        {
            using (MemoryStream mStream = new MemoryStream())
            {
                using (XmlTextWriter writer = new XmlTextWriter(mStream, Encoding.Unicode))
                {
                    XmlDocument document = new XmlDocument();
                    try
                    {
                        // Load the XmlDocument with the XML.
                        //Check if it is only XML 
                        if (XML.StartsWith("<?"))
                        {
                            document.LoadXml(XML);
                        }
                        else
                        {
                            //Split the string appended before XML
                            splitResults = XML.Split(xmlSeperators, 2, StringSplitOptions.None);
                            if (splitResults.Length > 1)
                            {
                                string d = "<?" + splitResults[1];
                                document.LoadXml(d);
                            }
                        }
                        writer.Formatting = Formatting.Indented;
                        // Write the XML into a formatting XmlTextWriter
                        document.WriteContentTo(writer);
                        //xx.WriteTo(writer);
                        writer.Flush();
                        mStream.Flush();
                        // Have to rewind the MemoryStream in order to read its contents.
                        mStream.Position = 0;
                        // Read MemoryStream contents into a StreamReader.
                        StreamReader sReader = new StreamReader(mStream);
                        // Extract the text from the StreamReader.
                        String FormattedXML = sReader.ReadToEnd();

                        if (splitResults[0] != null)
                        {
                            result = splitResults[0] + "\n" + FormattedXML;
                        }
                        else
                        {
                            result = FormattedXML;
                        }
                    }
                    catch (XmlException xe)
                    {
                        Log.Error(xe);
                        throw;
                    }                        
                }                   
            }
        }
        return result;
    }

      

+3


source to share


3 answers


The reason for receiving this warning is to XmlTextWriter.Dispose()

ensure that the underlying object is MemoryStream

also deleted. So when the area using

MemoryStream

ends, it will try to delete the object MemoryStream

and hence the warning.

Block

using

compiles into a block try-finally

. An inner block using

in your code will call Dispose

on yours writer

. This will call Dispose

to your MemoryStream

object mStream

. When exiting the internal control unit, the external unit will try to destroy the object writer

, but since it has already been deleted, you get a warning about the code analysis tool.

To get rid of the warning, you can remove the first statement using

and use a block try-finally

. But don't forget to set mStream

tonull

as soon as you enter the second operator using

. This was explained in CA2202: Do not delete objects multiple times



Your code will look like this:

public static String PrintXML(String XML)
{
    String result = "";
    string[] xmlSeperators = new string[] { "<?" };
    string[] splitResults = new string[2];

    if (!String.IsNullOrEmpty(XML))
    {
        MemoryStream mStream  = null;
        try
        {
            mStream = new MemoryStream();
            using (XmlTextWriter writer = new XmlTextWriter(mStream, Encoding.Unicode))
            {
                mStream = null; // important 
                XmlDocument document = new XmlDocument();
                try
                {
                    // Load the XmlDocument with the XML.
                    //Check if it is only XML 
                    if (XML.StartsWith("<?"))
                    {
                        document.LoadXml(XML);
                    }
                    else
                    {
                        //Split the string appended before XML
                        splitResults = XML.Split(xmlSeperators, 2, StringSplitOptions.None);
                        if (splitResults.Length > 1)
                        {
                            string d = "<?" + splitResults[1];
                            document.LoadXml(d);
                        }
                    }
                    writer.Formatting = System.Xml.Formatting.Indented;
                    // Write the XML into a formatting XmlTextWriter
                    document.WriteContentTo(writer);
                    //xx.WriteTo(writer);
                    writer.Flush();
                    mStream.Flush();
                    // Have to rewind the MemoryStream in order to read its contents.
                    mStream.Position = 0;
                    // Read MemoryStream contents into a StreamReader.
                    StreamReader sReader = new StreamReader(mStream);
                    // Extract the text from the StreamReader.
                    String FormattedXML = sReader.ReadToEnd();

                    if (splitResults[0] != null)
                    {
                        result = splitResults[0] + "\n" + FormattedXML;
                    }
                    else
                    {
                        result = FormattedXML;
                    }
                }
                catch (XmlException xe)
                {
                    Log.Error(xe);
                    throw;
                }
            }
        }
        finally 
        {

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

        }
    }
    return result;
}

      

+3


source


You can suppress the error warning, as the other answer says, but that fixes the problem by actually calling the method .Dispose()

only once in your code and only after you're done working with it. The disposed object will throw a System.ObjectDisposedException if you want it again, but not sure. The correct delete method can be called on the object multiple times and will / cannot generate an error for you. But this is not guaranteed.

A fix for this was stated in the Microsoft Developer Network document.



To correct a violation of this rule, change your implementation so that, regardless of the code path, Dispose is called only once on an object.

More details: http://msdn.microsoft.com/en-us/library/ms182334.aspx

0


source


This happens when you have nested statements using

where the inner statement contains a resource from the outer statement. In this case, XmlTextWriter

will dispose MemoryStream

when it is deleted and then the external operator using

will force it to be deleted a second time.

You can manually remove the MemoryStream by replacing the outer statement using

with try / finally:

MemoryStream mStream = null;
try
{
    mStream = new MemoryStream();
    using (XmlTextWriter writer = new XmlTextWriter(mStream, Encoding.Unicode))
    {
      mStream = null;
     ...
    }
}
finally
{
    if(mStream != null)
        mStream.Dispose();
}

      

(see http://msdn.microsoft.com/en-us/library/ms182334.aspx )

0


source







All Articles