Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#Xml序列化程序将列表反序列化为计数为0而不是null_C#_Xml_Serialization_Xmlserializer - Fatal编程技术网

C#Xml序列化程序将列表反序列化为计数为0而不是null

C#Xml序列化程序将列表反序列化为计数为0而不是null,c#,xml,serialization,xmlserializer,C#,Xml,Serialization,Xmlserializer,我对幕后的工作方式感到困惑。我有一个将XML反序列化为对象的类。我看到的是以下两个元素,它们不是反序列化Xml的一部分 [XmlRootAttribute("MyClass", Namespace = "", IsNullable = false)] public class MyClass { private string comments; public string Comments { set { comments = value; }

我对幕后的工作方式感到困惑。我有一个将XML反序列化为对象的类。我看到的是以下两个元素,它们不是反序列化Xml的一部分

[XmlRootAttribute("MyClass", Namespace = "", IsNullable = false)]
public class MyClass
{
    private string comments;
    public string Comments
    {
        set { comments = value; }
        get { return comments; }
    }

    private System.Collections.Generic.List<string> tests = null;
    public System.Collections.Generic.List<string> Tests
    {
        get { return tests; }
        set { tests = value; }
    }
}
[XmlRootAttribute(“MyClass”,Namespace=”“,IsNullable=false)]
公共类MyClass
{
私有字符串注释;
公共字符串注释
{
设置{comments=value;}
获取{返回注释;}
}
private System.Collections.Generic.List tests=null;
公共系统.Collections.Generic.List测试
{
获取{返回测试;}
设置{tests=value;}
}
}
让我们以以下XML为例:

<MyClass>
  <SomeNode>value</SomeNode>
</MyClass>

价值
您注意到测试和注释不是XML的一部分

当这个XML被反序列化时,注释为null(这是应该的),Tests是一个计数为0的空列表


如果有人能向我解释这一点,我将不胜感激。我更喜欢的是,如果XML中缺少
,那么列表应该保持为空,但是如果节点
存在,则应分配列表。

您观察到的是,在反序列化开始时,
XmlSerializer
会自动预分配引用可修改集合(如
list
)的成员。我不知道有任何地方记录了这种行为。它可能与到中描述的行为有关,该行为说明,由于
XmlSerializer
,如果预分配的集合包含默认项,则反序列化的项将附加到该集合中-可能会复制内容。微软可能只是选择在反序列化开始时预先分配所有可修改的集合,作为实现这一点的最简单方法

这个答案的解决方法,即使用代理数组属性,也适用于这里。由于数组不能追加到,因此,
XmlSerializer
必须累加所有值,并在反序列化完成时将其设置回原位。但是如果从未遇到相关标记,
XmlSerializer
显然不会开始累积值,因此不会调用数组setter。这似乎可以防止默认预分配您不想要的集合:

[XmlRootAttribute("MyClass", Namespace = "", IsNullable = false)]
public class MyClass
{
    private string comments;
    public string Comments
    {
        set { comments = value; }
        get { return comments; }
    }

    private System.Collections.Generic.List<string> tests = null;

    [XmlIgnore]
    public System.Collections.Generic.List<string> Tests
    {
        get { return tests; }
        set { tests = value; }
    }

    [XmlArray("Tests")]
    public string[] TestsArray
    {
        get
        {
            return (Tests == null ? null : Tests.ToArray());
        }
        set
        {
            if (value == null)
                return;
            (Tests = Tests ?? new List<string>(value.Length)).AddRange(value);
        }
    }
}
[XmlRootAttribute(“MyClass”,Namespace=”“,IsNullable=false)]
公共类MyClass
{
私有字符串注释;
公共字符串注释
{
设置{comments=value;}
获取{返回注释;}
}
private System.Collections.Generic.List tests=null;
[XmlIgnore]
公共系统.Collections.Generic.List测试
{
获取{返回测试;}
设置{tests=value;}
}
[XmlArray(“测试”)]
公共字符串[]TestsArray
{
得到
{
返回(Tests==null?null:Tests.ToArray());
}
设置
{
如果(值==null)
返回;
(测试=测试??新列表(值.长度)).AddRange(值);
}
}
}

示例显示,
测试
仅在适当时分配。

在谷歌搜索相同问题后,我们在此结束。 我们最终做的是在反序列化之后检查Count==0,并手动将属性设置为null

...
var varMyDeserializedClass = MyXmlSerializer.Deserialize(new StringReader(myInput));
if (varMyDeserializedClass.ListProperty.Count == 0)
{
  varMyDeserializedClass.ListProperty = null;
}
...

这是一种廉价的解决方法,但提供了预期的结果,有助于避免重构或重新设计。

当您将
[System.Xml.Serialization.xmlement(IsNullable=true)]
应用于属性时,反序列化后列表将为空。

另一种可能是使用“magic”“Specified”后缀:


如果指定了序列化字段/属性XXX和布尔属性XXX,然后根据是否设置了主字段/属性来设置bool属性。

@gdir您是说当您序列化此字段/属性时,列表的值将为null而不是空列表?不,我想问的是,因为测试不是xml的一部分,所以序列化时,它应该为null而不是空列表。这有意义吗?OP的问题是关于反序列化而不是序列化。当对上面的XML进行反序列化时,将分配
测试
集合,即使
从未出现在XML中。(顺便说一句,我可以复制它。)编辑为反序列化,我不知道这种行为记录在什么地方。当
完全丢失时,您不希望分配列表。当存在空的
节点时,您想要什么?
public bool TestsSpecified {get;set;}