Unsafe C# - Converting Longs to Byte Arrays

In my previous post on converting enums to bytes I didn't achieve any noticeable speed up using unsafe code, probably because the safe conversion is so simple. What about a more complex conversion that could be done in a different way using unsafe code?

A 64-bit long can be broken down into 8 bytes using bit shifting. If we simply case the long to a byte then we'll take the rightmost 8-bits and discard the rest. By repeatedly bit shifting the long 8 bits to the right and casting we can chop the long up into 8-bit segments and get ourselves a byte array containing the long:

private static byte[] SafeLongToBytes(long value)
{
    var bytes = new byte[8];
    bytes[0] = (byte) value;
    bytes[1] = (byte) (value >> 8);
    bytes[2] = (byte) (value >> 16);
    bytes[3] = (byte) (value >> 24);
    bytes[4] = (byte) (value >> 32);
    bytes[5] = (byte) (value >> 40);
    bytes[6] = (byte) (value >> 48);
    bytes[7] = (byte) (value >> 56);
    return bytes;
}

We can do this in a simpler way using unsafe code. If we take a pointer to the byte array then we can write our long directly to the memory taken up by the byte array:

private static unsafe byte[] UnsafeLongToBytes(long value)
{
    var bytes = new byte[8];
    fixed (byte* pointer = bytes)
    {
        *(long*)pointer = value;
    }
    return bytes;
}

The main difference between the code here and the enum conversion in the last post is the use of the fixed block. This is necessary because the byte array will be allocated on the heap and we don't want the garbage collector moving it around whilst whilst we're playing with memory addresses. This wasn't necessary for the enum conversion because the enum was allocated on the stack.

Is this any quicker? Yes - the safe version was about 17% slower in rough tests on my laptop. The full code of the timing application can be found here.

Is that enough of an increase to warrant added unsafe code to your assembly? Well turns out that it doesn't matter... Whilst typing up this post I found out about the BitConverter class that has a long to byte array method. Flipping it open with ILSpy shows that its identical to the unsafe code above!