Search code examples
c#.net-4.0protobuf-net

protobuf-net: ProtoException in serializing and deserializing nullable enum with length prefix


This code reproduces the problem:

Type Resolver(int fieldNumber)
{
    return typeof(ConsoleColor?);
}

var stream = new MemoryStream();
ConsoleColor? obj = ConsoleColor.Green;
Serializer.NonGeneric.SerializeWithLengthPrefix(stream, obj, PrefixStyle.Base128, 1);

stream.Position = 0;
Serializer.NonGeneric.TryDeserializeWithLengthPrefix(stream, PrefixStyle.Base128, Resolver, out var dd);
//EXCEPTION!!!

I am simply serializing a nullable enum value. But when I try to deserialize, I get below exception:

ProtoBuf.ProtoException: Invalid wire-type; this usually means you have over-written a file without truncating or setting the length; see https://stackoverflow.com/q/2152978/23354'

What am I doing wrong? Is there any way to fix or work around the issue? I am using version 2.4.6 of protobuf-net library. (Cannot move to 3.x because I am stuck with .Net Framework 4.0).


Solution

  • When you pass a Nullable<T> into an API that takes object, it is boxed, and the boxing rules for Nullable<T> are special: it boxes to either a regular null, or a box of T, not a box of T?; in other words: an object value never contains a nullable value-type. Because of this, from the library's perspective you sent a ConsoleColor, not a ConsoleColor?, so:

    Type Resolver(int fieldNumber)
    {
        return typeof(ConsoleColor);
    }
    

    As a side note, though: the resolver API is very specific and niche, and there are usually better ways to do things. If you can tell me what you're trying to achieve, I can probably offer more guidance.

    (I'm trying to think whether there is ever a scenario where the resolver could meaningfully return a typeof(Nullable<T>) for some T - we could perhaps have the library just unwrap the nullable itself, or raise a more meaningful message)