C'è un modo meno doloroso per GetBytes per un buffer non a partire da 0?
-
22-09-2019 - |
Domanda
che sto avendo a che fare con i byte grezzi in un progetto e ho bisogno di fare qualcosa di simile in fondo
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];
}
Mi sento come questo è così sbagliato ma non riesco a trovare niente di meglio modo di farlo. C'è un modo più semplice?
Soluzione
BinaryWriter è molto efficiente:
byte[] ToBytes() {
var ms = new MemoryStream(somelength);
var bw = new BinaryWriter(ms);
bw.Write(SomeShort);
bw.Write(SomeOtherShort);
return ms.ToArray();
}
Altri suggerimenti
Non è necessario inizializzare tmp
ad un nuovo array. BitConverter.GetBytes
crea un nuovo array e lo restituisce per voi. Non c'è molto che tu possa fare GetBytes
ma è possibile utilizzare metodi come Buffer.BlockCopy
per semplificare l'operazione di copia.
Se non stai facendo questo in una performance-critical di codice, si può andare un po 'LINQy e fare cose come:
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();
Se si conosce la dimensione in anticipo (avere un insieme di tipi di valore) si potrebbe usare una struct e assegnare i valori nella struct. Quindi utilizzare il codice unsafe
per copiare i byte grezzi. Vorrei ancora consigliare contro di essa meno che non sia realmente necessario per scopi di velocità. E si potrebbe pensare che è doloroso:)
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;
}
Just po-shift ...
buffer[0]=(byte)SomeShort;
buffer[1]=(byte)(SomeShort >> 8);
buffer[2]=(byte)SomeOtherShort;
buffer[3]=(byte)(SomeOtherShort >> 8);
Questo significa anche che si è in completo controllo della endian-ness (in questo caso, little-endian)
È possibile rendere il codice un po 'più corto utilizzando Array.Copy, ma non non c'è alcun GetBytes sovraccarico o equivalente in BitConverter che pone il byte direttamente nel buffer.
BinaryWriter su un < a href = "http://msdn.microsoft.com/en-us/library/system.io.memorystream.aspx" rel = "nofollow noreferrer"> MemoryStream è ciò che si vuole?
Si noti che, adottando le convenzioni API di BitConverter che non ti piace, si sta facendo lo stesso problema per gli utenti della vostra classe. Invece, scrivere un metodo che accetta un BinaryWriter e serializza la classe in esso, questo si estende bene quando la classe è incorporato in qualche altro oggetto.