C#でbyte[] to int[] とか int[] to byte[]する
オンラインゲームの実装でプリミティブなデータを弄る機会があったので小ネタ投稿
BitConverterの内部実装
BitConverter.cs referencesource.microsoft.com
直接ポインタを操作するので、fixedでアドレスを固定。 byte型のポインタをそれぞれの型のポインタとして再解釈しているだけっぽい。逆も然り。
GCが絡むと複雑かと思ったけど、アドレスさえ固定すればC/C++みたいに自由が効くようになるのか~ (unsafeも忘れずに!)
実装結果
T[ ] to byte[ ]
public static unsafe byte[] ToBytes<T>(T[] array) where T : unmanaged { byte[] bytes = new byte[sizeof(T) * array.Length]; for (int i = 0; i < array.Length; i++) { fixed (byte* numPtr = &bytes[i * sizeof(T)]) { *(T*)numPtr = array[i]; } } return bytes; }
確保するバイト列は型のサイズごとにアラインすればOK。
unmanaged制約は加えたけど、多分不十分だし確実に動かすならジェネリクスじゃない方がいいかも。
byte[ ] to T[ ]
public static unsafe T[] Convert<T>(byte[] bytes) where T : unmanaged { T[] result = new T[bytes.Length / sizeof(T)]; for (int i = 0; i < result.Length; i++) { fixed (byte* numPtr = &bytes[i * sizeof(T)]) { result[i] = *(T*)numPtr; } } return result; }
さっきの逆バージョン。
この場合、byte列が指定の型にアラインされてないとアクセス違反なるので、弾いてあげる必要がある。
最低限の例外を加えたものは冒頭のリポジトリに挙げました。