I'm trying to create a packet struct that is basically a byte builder of fixed length. I have a WriteByte function written in 3 different ways. Just wondering which is best (or if there's a better way altogether) and which will keep the GC happy. BTW, I have a Position field that has to be updated when a byte(s) is written. The functions will expand to include WriteUInt16, WriteFloat etc... Not sure what the best approach is. Any advice is appreciated.
- Should this be a struct? I'd like to do as little allocation as possible because these Packs will be created very frequently.
- Should I put the WriteByte in the struct itself as a method (option 1), as an extension of Pack (passed by ref) (option 2), or just use a static helper class (passed by ref) (option 3)?
Here's the code:
public struct Pack
{
public byte[] Data { get; internal set; }
public int Pos { get; internal set; }
public Pack(byte opcode, ushort size)
{
++size; // make room for byte opcode
Data = new byte[2 + size]; // make room to prepend the size (ushort)
BitConverter.GetBytes(size).CopyTo(Data, 0);
Data[2] = opcode;
Pos = 3; // start writing at position 3
}
// option 1
// use: pack.WriteByte(0x01)
public void WriteByte(byte value) => Data[Pos++] = value;
}
public static class SPackExtensions
{
// option 2
// use: pack.WriteByte(0x01)
public static void WriteByte(ref this Pack pack, byte value)
{
pack.Data[pack.Pos++] = value;
}
}
public static class PackWriter
{
// option 3
// use: PackWriter.WriteByte(ref pack, 0x01)
public static void WriteByte(ref Pack pack, byte value)
{
pack.Data[pack.Pos++] = value;
}
}