MemoryPackで同じ値をシリアライズしても同じバイト列にならないことがある
同じデータをシリアライズしているのに、バイト列が変わることがある問題に遭遇しました。
何が違っていたのか
原因はint?の未初期化パディング。
MemoryPackはメモリ配置をそのまま書き込むため、値が同じでもパディング部分のバイト列が変わることがあります。報告したIssue
例えば今回の環境では、int?には以下のように3バイトのパディングがありました。ここは規格上不定なので、何が入っていても文句は言えません。
hasValue パディング value
1バイト 3バイト 4バイトMemoryPackはここも含めて書き込むので、バイト列が変わる、ということでした。
もちろんパディングは使わない領域なので、デシリアライズした結果は同じになります。
解決策
v1.22.0で追加されたSafeNullable<T>に置き換えることで対処できます。
- public int? IntValue { get; set; }
+ public SafeNullable<int> IntValue { get; set; }int?以外にも、short?、long?、float?、double?、DateTime?、Guid?、decimal?など、パディングが入る型は注意。enum?は基底型によります。
また、独自のunmanaged structも内部にパディングがあれば同様です。こちらはSafeNullable<T>で包んでも内部のパディングまでは除去されません。実装