In C#, is it possible to cast a byte array into another type without creating a new array?

扶醉桌前 提交于 2020-01-24 21:08:48

问题


I have a byte[] object that I'm using as a data buffer.

I want to "read" it as an array of a either primitive/non-primitive structs without duplicating the byte[] data in memory.

The goal would be something like:

byte[] myBuffer;

//Buffer is populated

int[] asInts = PixieDust_ToInt(myBuffer);
MyStruct[] asMyStructs = PixieDust_ToMyStruct(myBuffer);

Is this possible? If so, how?


回答1:


You will not be able to do this. To have a MyStruct[] you'll need to actually create such an array of that type and copy the data over. You could, in theory, create your own custom type that acted as a collection, but was actually just a facade over the byte[], copying the bytes out into the struct objects as a given value was accessed, but if you end up actually accessing all of the values, this would end up copying all of the same data eventually, it would just potentially allow you to defer it a bit and may be helpful if you only actually use a small number of the values.




回答2:


Consider class System.BitConverter

This class has functions to reinterpret the bytes starting at a given index as an Int32, Int64, Double, Boolean, etc. and back from those types into a sequence of bytes.

Example:

int32 x = 0x12345678;
var xBytes = BitConverter.GetBytes(x);
// bytes is a byte array with length 4: 0x78; 0x56; 0x34; 0x12
var backToInt32 = BitConverter.ToInt32(xBytes, 0);

Or if your array contains mixed data:

double d = 3.1415;
int16 n = 42;
Bool b = true;
Uint64 u = 0xFEDCBA9876543210;

// to array of bytes:
var dBytes = BitConverter.GetBytes(d);
var nBytes = BitConverter.GetBytes(n);
var bBytes = BitConverter.GetBytes(b);
var uBytes = BitConterter.GetBytes(u);
Byte[] myBytes = dBytes.Concat(nBytes).Concat(bBytes).Concat(uBytes).ToArray();

// startIndexes in myBytes:
int startIndexD = 0;
int startIndexN = dBytes.Count();
int startIndexB = startIndexN + nBytes.Count();
int startIndexU = startIndexB + bBytes.Count();

// back to original elements
double dRestored = Bitconverter.ToDouble(myBytes, startIndexD);
int16 nRestored = BitConverter.ToInt16(myBytes, startIndexN);
bool bRestored = BitConverter.ToBool(myBytes, startIndexB);
Uint64 uRestored = BitConverter.ToUint64(myBytes, startIndexU);



回答3:


Is it possible? Practically, yes!

Since .NET Core 2.1, MemoryMarshal lets us do this for spans. If you are satisfied with a span instead of an array, then yes.

var intSpan = MemoryMarshal.Cast<byte, int>(myByteArray.AsSpan());

The int span will contain byteCount / 4 integers.

As for custom structs... The documentation claims to require a "primitive type" on both sides of the conversion. However, you might try using a ref struct and see that is the actual constraint. I wouldn't be surprised if it worked!

Note that ref structs are still very limiting, but the limitation makes sense for the kind of reinterpret casts that we are talking about.

Edit: Wow, the constraint is much less strict. It requires any struct, rather than a primitive. It does not even have to be a ref struct. There is only a runtime check that will throw if your struct contains a reference type anywhere in its hierarchy. That makes sense. So this should work for your custom structs as well as it does for ints. Enjoy!




回答4:


The closest you will get in order to convert a byte[] to other base-types is

Byte[] b = GetByteArray();

using(BinaryReader r = new BinaryReader(new MemoryStream(b)))
{
    r.ReadInt32();
    r.ReadDouble();
    r.Read...();
}

There is however no simple way to convert a byte[] to any kind of object[]



来源:https://stackoverflow.com/questions/40110062/in-c-is-it-possible-to-cast-a-byte-array-into-another-type-without-creating-a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!