Мне сложно объяснить поведение на следующем примере:
[ProtoContract]
public class Class1Proto
{
[ProtoMember(1)]
public int data1 = 1;
[ProtoMember(2)]
public string data2 = "MYRANDOMSTRING";
}
[ProtoContract]
public class ProtoChunk
{
[ProtoMember(1)]
public List<Class1Proto> arr = new List<Class1Proto>();
public const int PageSize = 4096;
}
Использование:
byte[] page = new byte[ProtoChunk.PageSize];
ProtoChunk originalData = new ProtoChunk();
for (int i = 0; i < 100; i++)
{
Class1Proto p = new Class1Proto();
p.data1 = i * 2;
p.data2 = (i * 2).ToString();
originalData.arr.Add(p);
}
using (var memStream = new MemoryStream(page, writable:true))
{
Serializer.SerializeWithLengthPrefix(memStream, originalData, PrefixStyle.Fixed32);
}
using (var memStream = new MemoryStream(page, writable:false))
{
ProtoChunk deserializedData = Serializer.DeserializeWithLengthPrefix<ProtoChunk>(memStream, PrefixStyle.Fixed32);
}
Я ожидал, что originalData и deserializedData должны быть идентичными. И в основном они есть, за исключением того, что deserializedData.arr[0].data1 == 1 while originalData.arr[0].data1 == 0. Все остальные объекты идентичны, даже включая originalData.arr[0].data2 and deserializedData.arr[0].data2 (строковое поле).





protobuf-net предполагает "неявные нулевые значения по умолчанию" - то есть, если не указано иное, члены имеют значение по умолчанию, равное нулю, что означает: ноль не передается. Это не чисто произвольно - это на самом деле спецификация "proto3" (ну ... более или менее; в "proto3" ноль - это разрешенное значение по умолчанию для Только).
Ваш код - особенно инициализатор свойства - действует так, как если бы он имеет значение по умолчанию 1, поэтому: когда ноль не передается, 1 все еще применяется вашим конструктором, и это становится значением (десериализация в protobuf - это " операция слияния - сохраняются ранее существовавшие значения, опять же в соответствии со спецификацией).
Параметры:
[DefaultValue(1)]SkipConstructor = true в [ProtoContract]RuntimeTypeModel.Default.ImplicitZeroDefault = false;Лично я бы использовал первый вариант.