2013-05-05 72 views
9

来到protobuf网,真棒!我有一个关于空列表序列化的问题。Protobuf网空列表

我开始通过声明我想要序列化对象:

[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),当我deserialse这个对象永远是零。这是有道理的看protobuf的约定,我目前解决此通过添加以下方法:

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

我的问题是我是否可以与附加attirbute将实现更简洁时尚此相同的功能,有可能将空/空对象初始化为空而不是空?

回答

5

如果您试图防范空列表,您可以尝试在属性获取器中进行延迟加载。

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

这样你就可以让串行器返回null。

+0

这是我没有考虑过的可能性,如果可以的话,会投票给你。我仍然主要想知道是否有一个属性可以为我做到这一点。 – CanCan 2013-05-05 21:34:56

+0

您是否尝试过[DefaultValue]属性?不知道你是否可以初始化列表,但值得一试。 – Jras 2013-05-05 21:41:00

+0

@Jras我确实考虑过添加这样的内容,但是每次看到它,事实上都会让人们的代码变得更糟,而不是更好 – 2013-05-06 00:06:44

6

在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>()); } } 

而且注意,这个建议不只是序列化:它是如何避免任意的空引用异常。人们通常不希望子集合为空。

+0

是否有任何理由不在私人项目字段上初始化收集?我可以看到,如果你没有访问Items属性的getter,那么你不会挂在一个空的集合引用上,但是你每次都支付空值检查的代价。它只是情景? – Shaun 2013-11-26 16:40:28