How to deserialize null array to null in c#? How to deserialize null array to null in c#? arrays arrays

How to deserialize null array to null in c#?


If you use an array instead of a list it works as expected

public class Command{    [XmlArray(IsNullable = true)]    public Parameter[] To { get; set; }}


Ugh, annoying isn't it. You can see it being doing by running sgen.exe on your assembly with the /keep and /debug options so you can debug the deserialization code. It looks roughly like this:

global::Command o;o = new global::Command();if ((object)(o.@To) == null) o.@To = new global::System.Collections.Generic.List<global::Parameter>();global::System.Collections.Generic.List<global::Parameter> a_0 = (global::System.Collections.Generic.List<global::Parameter>)o.@To;// code elided//...while (Reader.NodeType != System.Xml.XmlNodeType.EndElement && Reader.NodeType != System.Xml.XmlNodeType.None) {  if (Reader.NodeType == System.Xml.XmlNodeType.Element) {    if (((object)Reader.LocalName == (object)id4_To && (object)Reader.NamespaceURI == (object)id2_Item)) {      if (!ReadNull()) {        if ((object)(o.@To) == null) o.@To = new global::System.Collections.Generic.List<global::Parameter>();        global::System.Collections.Generic.List<global::Parameter> a_0_0 = (global::System.Collections.Generic.List<global::Parameter>)o.@To;        // code elided        //...      }      else {        // Problem here:        if ((object)(o.@To) == null) o.@To = new global::System.Collections.Generic.List<global::Parameter>();        global::System.Collections.Generic.List<global::Parameter> a_0_0 = (global::System.Collections.Generic.List<global::Parameter>)o.@To;      }    }  }  Reader.MoveToContent();  CheckReaderCount(ref whileIterations1, ref readerCount1);}ReadEndElement();return o;

No less than 3 places where it makes sure the @To property isn't null. The first one is somewhat defensible, hard to deserialize data when the structure doesn't exist. The second one does the null test again, that's the only real good one. The third one is the problem, ReadNull() returned true but it still creates a non-null property value.

If you want to differentiate between empty and null then you have no good solution but edit this code by hand. Do this only if you are really desperate and the class is 100% stable. Well, don't do it. João's solution is the only good one.


I agree with @Oliver's comment, but you can solve it like this if you absolutely need it to return null. Instead of using an automatic property, create your own backing field.

List<Parameter> _to;public List<Parameter> To{    get    {        if (_to != null && _to.Count == 0) return null;        return _to;    }    set { _to = value; }}