C# Xml Serializer 将列表反序列化为 0 而不是 null

标签 c# xml serialization xmlserializer

我很困惑 XmlSerializer 在幕后工作。我有一个将 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; }
    }
}

让我们以下面的 XML 为例:

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

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

当此 XML 被反序列化时,Comments 为 null(这是预期的)并且 Tests 是一个计数为 0 的空列表。

如果有人能向我解释一下,我将不胜感激。我更喜欢的是,如果 <Tests> XML 中缺少,则列表应保持为空,但如果(可能为空)节点 <Tests />存在则应该分配列表。

最佳答案

您观察到的是引用可修改集合的成员,例如 List<T>XmlSerializer 自动预分配在反序列化的开始。我不知道有任何地方记录了这种行为。这可能与 this answer 中描述的行为有关给 XML Deserialization of collection property with code defaults ,这说明,自 XmlSerializer supports adding to get-only and pre-allocated collections ,如果预分配的集合包含默认项,那么反序列化的项将附加到它——可能会重复内容。 Microsoft 可能只是选择在反序列化开始时预先分配所有 可修改的集合作为实现此目的的最简单方法。

该答案的解决方法,即使用代理数组属性,在这里也适用。由于无法附加数组,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);
        }
    }
}

样本 .Net fiddle表明 Tests仅在适当的时候分配。

关于C# Xml Serializer 将列表反序列化为 0 而不是 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45358844/

相关文章:

java - 如何序列化 android.location 类?

Java 序列化问题

c# - 远程服务器返回错误 : 227 Entering Passive Mode (500 oops vs_utility_recv_peek: no data)

c# - 在 Entity Framework 5 中创建模拟上下文时遇到问题

c# - 有什么方法可以更快地在 Canvas 上渲染大量移动对象(C# w/WPF)

c# - 根据父节点的属性获取子节点

Java序列化和反序列化

c# - 在底层 mysql 连接丢失后,有什么方法可以恢复(长)事务吗?

java - 如何解决使用 jersey 在 java Rest 服务中生成 xml 的问题?

c# - LINQ 选择特定元素