How do I make repeatable properties 'optional' in protobuf for c#

5,202 views
Skip to first unread message

Manh Do

unread,
Jun 21, 2010, 9:35:06 PM6/21/10
to Protocol Buffers
I am working a project where we need to determine if a protobuf list
have is null or not in the protocol buffer.

The problem is the generated c# automatically instantiates the list.

IE. Protocol:
message B {
repeated A MyList = 0;
}

Generated C#:

private readonly global::System.Collections.Generic.List<A> _MyList =
new global::System.Collections.Generic.List<A>();
[global::ProtoBuf.ProtoMember(0, Name=@"MyList", DataFormat =
global::ProtoBuf.DataFormat.Default)]
public global::System.Collections.Generic.List<A> MyList
{
get { return _MyList ; }
}

The problem with this is I cannot determine if the list is null. I am
using an empty list as a way to remove all objects.

Is there a way where I can make the generator not automatically
instantiate the list? Better yet, how do I check for default values in
protocol buffer C#? I know you can check for
'default(typeof(MyType));'.

Thanks for the help!

-Manh

Kenton Varda

unread,
Jun 22, 2010, 1:59:57 PM6/22/10
to Manh Do, Protocol Buffers
Protocol Buffers has no concept of "null".  Lists can be empty, but not "null".


--
You received this message because you are subscribed to the Google Groups "Protocol Buffers" group.
To post to this group, send email to prot...@googlegroups.com.
To unsubscribe from this group, send email to protobuf+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/protobuf?hl=en.


Marc Gravell

unread,
Jun 22, 2010, 4:21:45 PM6/22/10
to Kenton Varda, Manh Do, Protocol Buffers
Kenton is of course quite correct. There is no *native* distinction between a null list and an empty list in the raw protobuf data stream. There *are* some ways of working around that, to distinguish between the two, but not when using the code-generation from .proto.

Marc
--
Regards,

Marc

Manh Do

unread,
Jun 22, 2010, 4:25:20 PM6/22/10
to Protocol Buffers
What are your suggestions? One option that I was thinking is to add a
boolean field in the message that determines if the list is empty or
not. What do you think?
> >> protobuf+u...@googlegroups.com<protobuf%2Bunsubscribe@googlegroups.c om>
> >> .
> >> For more options, visit this group at
> >>http://groups.google.com/group/protobuf?hl=en.
>
> >  --
> > You received this message because you are subscribed to the Google Groups
> > "Protocol Buffers" group.
> > To post to this group, send email to prot...@googlegroups.com.
> > To unsubscribe from this group, send email to
> > protobuf+u...@googlegroups.com<protobuf%2Bunsubscribe@googlegroups.c om>
> > .

Marc Gravell

unread,
Jun 22, 2010, 4:31:21 PM6/22/10
to Manh Do, Protocol Buffers
That was exactly my thought. Something *broadly* like (untested):

    [ProtoMember(1)]
    public List<Foo> Foos {get;set;}

    [ProtoMember(2), DefaultValue(false)]
    private bool FoosHasValue {
        get { return Foos != null; }
        set { Foos = value ? ( Foos ?? new List<Foo>() ) : null; }
    }

Note that this may have some impact if you are concatenating messages, and is slightly hacky - Kenton will be tutting, I expect ;p

Marc

To unsubscribe from this group, send email to protobuf+u...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/protobuf?hl=en.




--
Regards,

Marc

Manish Agrawal

unread,
May 13, 2012, 10:14:36 PM5/13/12
to prot...@googlegroups.com, Manh Do
I am trying to use this list structure to save a collection of protobufs in a database as a Byte[]. I created my PBFs, and then created another buffer with an internal List of PBFs as follows. The problem is that during serialization, I get an unexpected sub-type error. My questions are:

1. What is the recommended way to save a collection of PBFs in a database cell?
2. How can I serialize a PBF which has a field which is a collection of other PBFs?

[ProtoContract]
    class Buffers
    {
        [ProtoMember(2)]
        public int user_id { get; set; }
...
    }

[ProtoContract]
    class Albums : Buffers
    {
        [ProtoMember(4)]
        public int album_id { get; set; }
...   
  }

   [ProtoContract]
    class BuffersList
    {
        [ProtoMember(1)]
        public List<Buffers> Items { get; set; }

        public BuffersList()
        {
            Items = new List<Buffers>();
        }
...
    }

Now when I try:

Serializer.NonGeneric.SerializeWithLengthPrefix(<MemoryStream>, <BuffersList>, PrefixStyle.Base128, field);

the above line generates the error message: System.InvalidOperationException: Unexpected sub-type: Albums

Thanks
Manish

On Tuesday, June 22, 2010 4:31:21 PM UTC-4, Marc Gravell wrote:
That was exactly my thought. Something *broadly* like (untested):

    [ProtoMember(1)]
    public List<Foo> Foos {get;set;}

    [ProtoMember(2), DefaultValue(false)]
    private bool FoosHasValue {
        get { return Foos != null; }
        set { Foos = value ? ( Foos ?? new List<Foo>() ) : null; }
    }

Note that this may have some impact if you are concatenating messages, and is slightly hacky - Kenton will be tutting, I expect ;p

Marc
Reply all
Reply to author
Forward
0 new messages