2
public class Warning
{

    public Warning()
    {

    }

    public Warning(String name, List<String> conflictList)
    {
        Name = name;
        ConflictList = conflictList;
    }

    public string Name 
    { 
        get; 
        set; 
    }

    public List<String> ConflictList
    {
        get;
        set; 
    }

    public static Warning ReadXML(string xml)
    {
        Warning warning = null;

        try
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Warning));
            using (StringReader sr = new StringReader(xml))
            {
                XmlTextReader xtr = new XmlTextReader(sr);
                warning = (Warning)serializer.Deserialize(xtr);
                xtr.Close();
                sr.Close();
            }
        }
        catch
        {
        }

        return warning;
    }

    public void Save(string filename)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(Warning));
        using (StreamWriter writer = new StreamWriter(filename))
        {
            serializer.Serialize(writer, this);
            writer.Close();
        }
    }
}

If I deserializing the following xml string and I get non-null values back for both Name and ConflictList. This is fine and what I expect.

Warning w1 = Warning.ReadXML(
    "<Warning><Name>test warning</Name><ConflictList><string>file1.txt</string></ConflictList></Warning>");

w1.Name returns "test warning" and w1.ConflictList returns a list containing the text "file1.txt"

However, if I deserialize the following xml string, w2.Name returns null, which i understand, but ConflictList is actually a list with a Count of 0. I expected it to be null as well. How come?

Warning w2 = Warning.ReadXML("<Warning></Warning>");

I am sure in some cases w1.ConflictList can return null if the element is not present in the xml string, but when does this happen?

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
bobbo
  • 845
  • 2
  • 14
  • 24

1 Answers1

0

I too would have expected it to leave it alone if it isn't in the xml, but I too can reproduce what you are saying, both "as is", and with [XmlElement(...)] on the member. I guess internally it is newing up the list "in case".

I also tried the alternative syntax just using a get and a lazy initializer, i.e.

// note: doesn't work; see answer text
private List<string> conflictList;
public List<String> ConflictList
{
    get { return conflictList ?? (conflictList = new List<string>()); }
}

but it still invokes this getter, even when no conflict data is included. And annoyingly the *Specified pattern only ever gets called for data that is specified - it doesn't get called for data that isn't specified, else you could do:

// note: doesn't work; see answer text
[XmlIgnore]
public bool ConflictListSpecified
{
    get { return ConflictList != null; }
    set { if (!value) ConflictList = null; }
}

Add to that the fact that serialization callbacks aren't supported in XmlSerializer and I'm out of options.

I've tested it back to .NET 2.0, and it behaves the same there too...

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900