-
Notifications
You must be signed in to change notification settings - Fork 6
Type Conversion
In certain cases, .NET types may differ between serialiser and deserialiser. Understanding these rules allows the graceful evolution of schema over time.
Here we consider the types of:
- complex type properties
- tuple member
Legend:
π always succeeds
π always fails
π depends upon value
Conversions that depend upon the value can not be relied upon unless you know 100% that out-of-range values will not be serialised.
Left column shows the input (serialised) type. Top row shows output (deserialised) types.
Byte | SByte | Int16 | UInt16 | Int32 | UInt32 | Int64 | UInt64 | Single | Double | Decimal | Boolean | Char | String | Empty | Byte[] | ArraySegment<byte> | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Byte | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
SByte | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Int16 | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
UInt16 | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Int32 | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
UInt32 | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Int64 | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
UInt64 | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Single | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Double | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Decimal | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Boolean | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Char | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
String | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Empty | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Byte[] | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
ArraySegment<byte> | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π |
Some observations:
- Widening integral types of the same sign always works.
- Converting signed to unsigned integers never works all the time.
- Converting unsigned to wider signed integral types always works.
- Narrowing integral types only works if the value received fits within the new type.
-
float
can always widen todouble
without loss of precision. - Integral types can always be converted to
decimal
without loss of precision. -
string
can only convert tochar
if the string has a single character. -
decimal
can convert tostring
as decimal values are encoded as strings during transport anyway. Conversely,string
can convert todecimal
if the string passesdecimal.TryParse
. -
byte[]
andArraySegment<byte>
are interchangeable.
In general, Dasher takes a very conservative view on conversions, actively enabling them when provably safe to do so. Cases that only work some of the time are artefacts of the MsgPack encoding used. MsgPack messages do contain some type information, but at a more restricted level than the .NET type system.
For contrast, here are the results for the same conversions using .NET's System.Convert.ChangeType(object, Type)
method.
Byte | SByte | Int16 | UInt16 | Int32 | UInt32 | Int64 | UInt64 | Single | Double | Decimal | Boolean | Char | String | Empty | Byte[] | ArraySegment<byte> | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Byte | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
SByte | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Int16 | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
UInt16 | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Int32 | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
UInt32 | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Int64 | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
UInt64 | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Single | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Double | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Decimal | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Boolean | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Char | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
String | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Empty | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
Byte[] | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | |
ArraySegment<byte> | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π | π |
These built-in conversions introduce policy, conventions and occasional loss of precision. Dasher may extend its conversion capabilities in future. Use the issue tracker for discussion.