I have a class that I serialize, then deserialize using Protobuf-net version r431 (probably a year old or so). The class contains an enum _type and a string called _band. In the constructor, _type is set to StationType.Other and _band is set to an empty string.
As you can see I create an object with data, serialize, then deserialize. The value of the enum _type (StationType.Streaming) is lost, while the _band (FM) is retained.
I feel this is an error, since the behavior is inconsistent. However, if I start the enum from the value of 1 instead of 0, everything works as expected (e.g. all values are retained).
Am I missing something here? See the code and the output below:
using System;
using System.IO;
using ProtoBuf;
namespace ProtoBufsWithEnums
{
class Program
{
static void Main(string[] args)
{
stn1 = new Station{Type = StationType.Streaming, Band = "FM"};
var ms1 = new MemoryStream();
Serializer.Serialize(ms1, stn1); // serialize
byte[] bytes = ms1.ToArray();
var ms2 = new MemoryStream(bytes);
Station stn2 = Serializer.Deserialize<Station>(ms2); // deserialize
Console.WriteLine("Type - Original {0}, New {1}", stn1.Type, stn2.Type);
Console.WriteLine("Band - Original {0}, New {1}", stn1.Band, stn2.Band);
}
}
[ProtoContract]
public enum StationType
{
[ProtoEnum(Name = "Streaming", Value = 0)]
Streaming = 0,
[ProtoEnum(Name = "Terrestrial", Value = 1)]
Terrestrial = 1,
[ProtoEnum(Name = "Other", Value = 2)]
Other = 2,
[ProtoEnum(Name = "Group", Value = 3)]
Group = 3
}
[ProtoContract]
public class Station
{
[ProtoMember(9)]
private StationType _type;
[ProtoMember(10)]
private string _band;
public Station()
{
_type = StationType.Other;
_band = "";
}
public StationType Type
{
get { return _type; }
set { _type = value; }
}
public string Band
{
get { return _band; }
set { _band = value; }
}
}
}
Output:
Type - Original Streaming, New Terrestrial
Type - Original FM, New FM
EDIT: Found issue 251 on the protobuf-net site, not sure if I am looking at the same issue or not. Not quite sure whether it has been fixed or not.
Here's the glitch:
public Station()
{
_type = StationType.Other;
_band = "";
}
protobuf-net makes some implicit assumptions about zero defaults. This works nicely in a lot of cases, but not all. The easiest way to help it here is to tell it that you are using a non-zero default:
[ProtoMember(9), DefaultValue(StationType.Other)]
private StationType _type;
Another option would be to tell it always to serialize it:
[ProtoMember(9, IsRequired = true)]
private StationType _type;
If you have lots of this, another option is to disable the "zero-default" behaviour, which can be done on a custom model:
var model = TypeModel.Create();
model.UseImplicitZeroDefaults = false;
then use model.Serialize(...) etc - but note that you should store and re-use a model like this (don't recreate it every time you need to serialize something), since that contains all the cached reflection/meta-programming output.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With