title: XmlSerializer and IEnumerable: Serialization possible w/o parameterless constructor: Bug?
body: <p>In our project we extensivly use the XmlSerializer. By chance I found a class w/o a parameterless contructor. I thought this must break the serialization process but it did not.</p>
  
  <p>By investigating this issue I found out, that the XmlSerializer behaves strange when serializing/deserializing an <em>IEnumerable</em>:</p>
  
  <ul>
  <li>All elements of the enumerable are serialized</li>
  <li>The class is required to implement an <em>Add(object)</em> method</li>
  <li>It ignores all other properties that may be in this class. </li>
  <li>It calls a getter with this property and reuses the returned instance for serialization (which allows the XmlSerializer to work w/o a parameterless constructor).</li>
  </ul>
  
  <p>Please have a look at the example that follows. Intersting parts are ODD1, ODD2. Note that good5 and good6 are false, when I expected them to be true. </p>
  
  <p>Is there a reason for this behaviour?  </p>
  
  <p>Can I make XmlSerializer reuse an instance returned by a property for deserialization when implementing IXmlSerializable by hand?</p>
  
  <pre><code>using System.Collections;
  using System.Collections.Generic;   
  using System.IO;    
  using System.Xml;
  using System.Xml.Schema;
  using System.Xml.Serialization;
  
  namespace Test
  {
      public static class Program
      {
          public static void Main()
          {
              HostingClass host = new HostingClass();
  
              host.AutomaticSerialization.StringProperty = "AUTO";
              host.SelfImplementedSerialization.StringProperty = "SELF";
  
              bool good1 = host.AutomaticSerialization.FromConstructor == "PARAMETER";
              bool good2 = host.SelfImplementedSerialization.FromConstructor == "PARAMETER";
              bool good3 = host.AutomaticSerialization.StringProperty == "AUTO";
              bool good4 = host.SelfImplementedSerialization.StringProperty == "SELF";
  
              XmlSerializer serializer = new XmlSerializer(typeof(HostingClass));
  
              using (StringWriter sw = new StringWriter())
              {
                  serializer.Serialize(sw, host);
  
                  using (StringReader sr = new StringReader(sw.ToString()))
                  {
                      host = (HostingClass)serializer.Deserialize(sr);
                  }
              }
  
              bool good5 = host.AutomaticSerialization.FromConstructor == null; //is false
              bool good6 = host.AutomaticSerialization.StringProperty == "AUTO"; //is false
  
              bool good7 = host.SelfImplementedSerialization.FromConstructor == null;
              bool good8 = host.SelfImplementedSerialization.StringProperty == "SELF";
  
          }
      }
  
      public class HostingClass
      {
          private SelfImplementedSerialization _selfImplementedSerialization;
          public SelfImplementedSerialization SelfImplementedSerialization
          {
              get
              {
                  return _selfImplementedSerialization
                         ?? (_selfImplementedSerialization = new SelfImplementedSerialization("PARAMETER"));
              }
              set { _selfImplementedSerialization = value; }
          }
  
          private AutomaticSerialization _automaticSerialization;
          public AutomaticSerialization AutomaticSerialization
          {
              get
              {
                  return _automaticSerialization
                         ?? (_automaticSerialization = new AutomaticSerialization("PARAMETER")); //the returned object is used while deserializing
              }
              set { _automaticSerialization = value; }
          }
      }
  
      public class SelfImplementedSerialization : IXmlSerializable, IEnumerable&lt;int&gt;
      {
          public SelfImplementedSerialization() { }
          public SelfImplementedSerialization(string parameter)
          {
              FromConstructor = parameter;
          }
  
          public string StringProperty { get; set; }
          [XmlIgnore]
          public string FromConstructor { get; set; }
  
          public void ReadXml(XmlReader reader)
          {
              reader.ReadStartElement();
              StringProperty = reader.ReadElementString("StringProperty");
              reader.ReadEndElement();
          }
  
          public void WriteXml(XmlWriter writer)
          {
              writer.WriteElementString("StringProperty", StringProperty);
          }
  
          public IEnumerator&lt;int&gt; GetEnumerator()
          {
              yield return 1;
              yield return 2;
          }
  
          IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
          public XmlSchema GetSchema() { return null; }
      }
  
  
      public class AutomaticSerialization : IEnumerable&lt;int&gt;
      {
          //ODD1: Serialization possible w/o public parameterless constructor
          //public AutomaticSerialization() {} 
          public AutomaticSerialization(string parameter)
          {
              FromConstructor = parameter;
          }
  
          //ODD2: Element not serialized, only the IEnumerable Interface is serialized
          [XmlElement("SP")]
          public string StringProperty { get; set; }
          [XmlIgnore]
          public string FromConstructor { get; set; }
  
          public IEnumerator&lt;int&gt; GetEnumerator()
          {
              yield return 1;
              yield return 2;
          }
  
          public void Add(object o)
          {
              //requirement of XmlSerializer when serializing IEnumerables
          }
  
          IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
      }
  }
  </code></pre>