今回のオチ
System.Buffers.Binary.BinaryPrimitives
クラスを使いましょう
エンディアンを固定でシリアライズしたい
long
の値をbyte[]
にしたい時、普通はSystem.BitConverter.GetBytes(long)
で困らないんですが、BitConverter
のエンディアンは固定じゃないんですよね。ランタイム依存です。普通はリトルエンディアンなんですが、一部 mono 環境なんかでビッグエンディアンな環境があるらしいんですよ、奥さん。
実行時にリトルエンディアン環境なのか、ビッグエンディアン環境なのかはBitConverter.IsLittleEndian
プロパティで確認できます。ついでにこのプロパティは Intrinsic なので JIT 定数になり、if
文を書くと JIT 時に分岐が消えます。愛してる定数。
たとえばファイルフォーマットなんかでエンディアンが決まってるもの扱う時に、BitConverter
を使うと厳密にはランタイム依存で正しく動きません。雑に動けばいいならばBitConverter
でいいんです、だって普通はリトルエンディアンだもん。
逆に TCP/IP なんかはビッグエンディアン固定です。(まあここは普通ライブラリ使うので直に書くことはないですが。)
長々と書いて何が言いたいのかというと、System.Buffers.Binary.BinaryPrimitives
を使うと、エンディアン固定で直列化できますよという話です。使い方はメソッド名見れば一目瞭然なんですが、例えばlong
をリトルエンディアンでSpan<byte>
にする時は
long value = 100L; Span<byte> buf = stackalloc byte[8]; BinaryPrimitives.WriteInt64LittleEndian(buf, value);
です。ビッグエンディアン用のメソッドもちゃんとあります。
1つだけ残念なことは、BinaryPrimitives
クラスは .NET Standard 2.1, .NET Core 2.1 以降でしか使えないことです。
.NET Framework にはありません。だって Windows はリトルエンディアンだもん (2回目)。