在c#中,是否可以在不创建新数组的情况下将字节数组强制转换为另一种类型?

本文关键字:数组 字节数 字节 情况下 转换 类型 另一种 是否 创建 新数组 | 更新日期: 2023-09-27 18:13:47

我有一个byte[]对象,我用它作为数据缓冲区。

我想"读取"它作为一个数组的基本/非基本结构,而不重复内存中的byte[]数据。

目标是这样的:

byte[] myBuffer;
//Buffer is populated
int[] asInts = PixieDust_ToInt(myBuffer);
MyStruct[] asMyStructs = PixieDust_ToMyStruct(myBuffer);

这可能吗?如果有,怎么做?

在c#中,是否可以在不创建新数组的情况下将字节数组强制转换为另一种类型?

可能吗?实际上,是的!

从。net Core 2.1开始,MemoryMarshal允许我们为span执行此操作。如果您对span而不是数组感到满意,那么可以。

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

int span将包含byteCount/4个整数。

至于自定义结构…文档声称在转换的两边都需要一个"原始类型"。但是,您可以尝试使用ref struct,并查看这是实际的约束。如果成功了,我一点也不惊讶!

请注意,refstruct仍然非常有限,但是这种限制对于我们正在讨论的那种重新解释强制转换是有意义的。

Edit:哇,约束没那么严格了。它需要任何结构体,而不是原语。它甚至不需要是ref struct。只有运行时检查会在结构体在其层次结构中任何位置包含引用类型时抛出。这说得通。这应该对你的自定义结构体和整型一样有效。享受吧!

您将无法这样做。要获得MyStruct[],您需要实际创建这种类型的数组并复制数据。理论上,您可以创建您自己的自定义类型,作为一个集合,但实际上只是一种假象byte[],复制字节到struct对象访问给定值,但实际上如果你访问所有的值,这将最终复制相同的所有数据最终,它就可能让你推迟,可能会有帮助如果你只使用少量的价值观。

考虑类System。BitConverter

这个类有函数将从给定索引开始的字节重新解释为Int32、Int64、Double、Boolean等类型,并从这些类型返回为字节序列。

的例子:

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);

或者如果数组包含混合数据:

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);

为了将byte[]转换为其他基本类型,最接近的方法是

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

然而,没有简单的方法将字节[]转换为任何类型的对象[]