You asked about managed arrays. If you are content to use fixed
/ unsafe
, this can be very fast.
struct
is assignable, like any primitive. Almost certainly faster than Buffer.BlockCopy()
or any other method, due to the lack of method call overhead:
public unsafe struct MyStruct //the actual struct used, contains all
{
public int a;
public unsafe fixed byte buffer[16];
public ulong b;
//etc.
}
public unsafe struct FixedSizeBufferWrapper //contains _only_ the buffer
{
public unsafe fixed byte buffer[16];
}
unsafe
{
fixed (byte* bufferA = myStructA.buffer, bufferB = myStructB.buffer)
{
*((FixedSizeBufferWrapper*)bufferA) =
*((FixedSizeBufferWrapper*)bufferB);
}
}
We cast fixed
-size byte
buffers from each of your original structs to the wrapper pointer type and dereference each pointer SO THAT we can assign one to the other by value; assigning fixed
buffers directly is not possible, hence the wrapper, which is basically zero overhead (it just affects values used in pointer arithmetic that is done anyway). That wrapper is only ever used for casting.
We have to cast because (at least in my version of C#) we cannot assign anything other than a primitive type (usually byte[]
) as the buffer, and we aren't allowed to cast inside fixed(...)
.
EDIT: This appears get translated into a call to Buffer.Memcpy()
(specifically Buffer.memcpy4()
in my case, in Unity / Mono) under the hood to do the copy.