Protobuf-Net Empty List

本文关键字:List Empty Protobuf-Net | 更新日期: 2023-09-27 18:12:18

碰到protobuf-net,棒极了!我有一个关于空列表序列化的问题。

首先声明要序列化的对象:

[ProtoContract]
class TestClass
{
    [ProtoMember(1)]
    List<int> _listOfInts = new List<int>();
    public TestClass() { }
    public List<int> ListOfInts
    {
        get { return _listOfInts; }
        set { _listOfInts = value; }
    }
}

如果_listOfInts是空的(但不是null),当我反序列化这个对象时,它将始终是空的。从protobuf约定来看,这是有意义的,我目前通过添加以下方法来解决这个问题:

[ProtoAfterDeserialization]
private void OnDeserialize()
{
    if (_listOfInts == null)
        _listOfInts = new List<int>();
}

我的问题是我是否可以以更简洁的方式实现相同的功能,可能有一个额外的属性,将null/empty对象初始化为空而不是空?

Protobuf-Net Empty List

这里有一个关于protobuf如何编码数据的基本问题:列表本身并不出现在数据中—只是元素。因此,没有明显的地方可以存储关于列表的信息。可以通过使用条件序列化发送一个布尔值来欺骗它,但坦率地说,这有点粗糙和丑陋——并且增加了复杂性。就我个人而言,我强烈建议从可能为空的列表中抽象化。例如:

private readonly List<Foo> items = new List<Foo>();
[ProtoMember(1)]
public List<Foo> Items { get { return items; } }

private List<Foo> items;
[ProtoMember(1)]
public List<Foo> Items { get { return items ?? (items = new List<Foo>()); } }

注意,这个建议不仅仅是关于序列化:它是关于避免任意的null引用异常。人们通常不希望子集合为空。

如果你想防止空列表,你可以尝试在属性getter中延迟加载。

public List<int> ListOfInts
{
    get { return _listOfInts ?? (_listOfInts = new List<int>()); }
    set { _listOfInts = value; }
}

这样你就可以允许序列化器返回null。

相关文章: