Details
-
Improvement
-
Resolution: Unresolved
-
Unknown
-
None
-
None
-
None
Description
Because of the way that .NET/C# treat enums, known serializers requires special code for handling them. Consider the following expression:
x => x.Es == E.A
where E is an enum and Es is an enum property configured to use the string enum representation.
This expression tree appears in code as:
x => Convert(x.Es, Int32) == 0
The enum value E.A is translated into 0 (zero) without any indication that it was ever an enum. So our serializer finder code has to say “oh, here’s an integer, I wonder if it might be an enum… let’s start walking up the tree to see if there is an enum serializer configured somewhere above us…” Most of the time it works because the immediate node above has the correct enum serializer configured. But it is possible to come up with cases where we serialize an actual integer as an enum when it should be serialized as a numeric type. For example:
x => x.P == (x.Es == E.A ? 42 : 144)
where x.P is an integer property and x.Es and E.A are as defined above.
When we ask KnownSerializersRegistry for serializers for 42 and 144, it will return the string enum serializer because it was pushed up from the x.Es node rather than the Int32Serializer from the x.P node.
Note that this can only happen when enums appear in the expression tree. In the most common cases when comparing a document field to an enum, the correct serializer is chosen. The default enum serializer uses an int32 representation - which although it is the incorrect serializer for a true int32 from a conceptual standpoint - the resulting representation will be identical; the BSON document will contain an int32. Thus our initial analysis of the problem is that although this is a shortcoming of the current known serializers implementation, it is unlikely to affect most users.