Is there a less painful way to GetBytes for a buff

2019-06-24 01:56发布

问题:

I am having to deal with raw bytes in a project and I need to basically do something like this

byte[] ToBytes(){
  byte[] buffer=new byte[somelength];
  byte[] tmp;
  tmp=BitConverter.GetBytes(SomeShort);
  buffer[0]=tmp[0];
  buffer[1]=tmp[1];
  tmp=BitConverter.GetBytes(SomeOtherShort);
  buffer[2]=tmp[0];
  buffer[3]=tmp[1];
}

I feel like this is so wrong yet I can't find any better way of doing it. Is there an easier way?

回答1:

BinaryWriter is very efficient:

    byte[] ToBytes() {
        var ms = new MemoryStream(somelength);
        var bw = new BinaryWriter(ms);
        bw.Write(SomeShort);
        bw.Write(SomeOtherShort);
        return ms.ToArray();
    }


回答2:

You don't need to initialize tmp to a new array. BitConverter.GetBytes creates a new array and returns it for you. There's not much you can do about GetBytes but you can use methods like Buffer.BlockCopy to simplify the copy operation.

If you're not doing this in a performance-critical piece of code, you can go a bit LINQy and do things like:

IEnumerable<byte> bytes = BitConverter.GetBytes(first);
bytes = bytes.Concat(BitConverter.GetBytes(second));
bytes = bytes.Concat(BitConverter.GetBytes(third));
// ... so on; you can chain the calls too
return bytes.ToArray();


回答3:

If you know the size beforehand (have a set of value types) you could use a struct and assign your values in the struct. Then use unsafe code to copy the raw bytes. I would still advise against it unless it's really necessary for speed purposes. And you might think it's painful :)

private struct MyStruct
{
    public short A;
    public short B;

    public MyStruct(short a, short b)
    {
        A = a;
        B = b;
    }
}

private unsafe byte[] UnsafeStruct(MyStruct myStruct)
{
    byte[] buffer = new byte[4]; // where 4 is the size of the struct
    fixed (byte* ptr = buffer)
    {
        *((MyStruct*)ptr) = myStruct;
    }
    return buffer;
}


回答4:

Just bit-shift...

buffer[0]=(byte)SomeShort;
buffer[1]=(byte)(SomeShort >> 8);
buffer[2]=(byte)SomeOtherShort;
buffer[3]=(byte)(SomeOtherShort >> 8);

This also means you are in complete control of the endian-ness (in this case, little-endian)



回答5:

You can make your code a little shorter by using Array.Copy, but no there isn't any GetBytes overload or equivalent in BitConverter that puts the bytes directly into your buffer.

Maybe BinaryWriter on a MemoryStream is what you want?

Note that by adopting the API conventions of BitConverter which you don't like, you're causing the same problem for users of your class. Instead, write a method which accepts a BinaryWriter and serializes your class into it, this extends nicely when your class is embedded in some other object.