Как сериализовать 64-битное перечисление в c# - PullRequest
8 голосов
/ 25 марта 2020
[Flags]
Enum xyz : UInt64
{
  a = 1,
  .
  .
  . 
  b = 17179869184,
}  

для сериализации Я использую:

[ProtoContract]
class ABC
{
  [ProtoMember(1)]
  public xyz name;
}

name = xyz.b;

Я получаю 0 при десериализации, так как я могу получить 64-битное число?

1 Ответ

4 голосов
/ 25 марта 2020

Здесь нужно взглянуть на две разные вещи; первое: пока вы присваиваете ненулевое значение, для большинства значений оно уже должно работать; тот факт, что вы видите ноль, говорит мне, что вы , вероятно, либо не присваиваете значение в первую очередь (значение по умолчанию для перечисления равно нулю, даже если вы не определяете что-нибудь с нуля), или вы используете перематываемый поток, но не перематывали; это работает на 2.4.4:

var obj = new ABC { name = xyz.a };
var ms = new MemoryStream();
Serializer.Serialize(ms, obj);
ms.Position = 0; // rewind
var clone = Serializer.Deserialize<ABC>(ms);
Console.WriteLine(clone.name); // a

Однако существует проблема с большими числами, так как protobuf определяет перечисления как 32-битные. Кодовая база v3 работает в этом направлении, поэтому в предварительных версиях v3 тот же код будет отлично работать и с b, но на v2 ваше значение b в настоящее время слишком велико и вызывает арифметическое переполнение c. В этом сценарии я бы подошел к этому с помощью свойства shadow:

public xyz name;

[ProtoMember(1)]
private ulong NameSerialized
{
    get => (ulong)name;
    set => name = (xyz)value;
}

Это будет работать на v2 или v3.

...