对于这个可怕的头衔感到抱歉,但老实说,我知道我想要什么,也不知道有什么不对......
基本上我有一个结构(我有250多个结构,但它们都遵循相同的想法),如下所示:
[StructLayout(LayoutKind.Explicit)]
public struct GenericPacket
{
[FieldOffset(0)]
public byte[] data;
[FieldOffset(0)]
public short packetid;
}
问题是字节数组是引用类型而short是值类型,它不允许将fieldoffset设置为相同的内存位置......
我真的很想不得不删除我写的所有结构,只是为了以不同的方式去做。所以这是我的问题,我怎么能以一种有效的方式使用它。基本上我要做的是:
socket.Receive(buff, 0, 0, SocketFlags.None);
GenericPacket packet = new GenericPacket();
packet.data = buff;
Console.WriteLine(packet.packetid);
它拒绝甚至编译,因为它不想生成struct /:
在任何人提出其他方法之前,我这样做的原因是它需要超高速...我可以使用ByteReader和其他方法(例如BitConverter)但它需要比这更快一点......
我开始使用Bitwise移位,但我需要一种更“动态”的方式来实现它,因为在我有一个数据包ID后,我会用另一个结构读取它,例如:
[StructLayout(LayoutKind.Explicit)]
public struct _03k
{
[FieldOffset(0)]
byte[] data;
[FieldOffset(0)]
short packetid;
[FieldOffset(2)]
short @null;
[FieldOffset(4)]
int major;
[FieldOffset(8)]
int minor;
[FieldOffset(12)]
int build;
}
而不是必须有很多内联“Bitwise shits”,我只是想要一个简单且非常快速的方法来做到这一点......似乎我得到了快速而不是简单/:
请帮助!不安全的代码是可以的,但也喜欢托管版本。
失败:(:记得你可以通过装箱将它们转换为引用类型(转换为类型对象)。但这会移除REAL返回类型并说它只是一个对象,无论如何使用XML文档你可以说谎返回类型? 无法正常工作D:
更新:好的,现在我有:
public struct GenericPacket
{
public short packetid;
public static GenericPacket ReadUsingPointer(byte[] data)
{
unsafe
{
fixed (byte* packet = &data[0])
{
return *(GenericPacket*)packet;
}
}
}
}
但是每次调用一个方法来转换它有点烦人:(任何人都有更多的建议吗?
谢谢,JD
答案 0 :(得分:1)
您只想将数组的前两个字节转换为short,这会如何构成任何性能问题?
packetid = ((short)data[0] << 8) | data[1];
如果你想要另一个字节,那么反过来。
编辑:
所以你想解析多个字段。那么,不要重新发明轮子。使用谷歌的协议缓冲区,它非常快速和有效,我怀疑你会遇到性能问题。这是一个.NET port.
答案 1 :(得分:1)
我刚刚发现你可以在结构中使用固定数组:
[StructLayout(LayoutKind.Explicit)]
unsafe struct Union
{
[FieldOffset(0)]
public short x;
[FieldOffset(0)]
public fixed byte y[2];
}
初始化:
var u = new Union();
byte[] y = new byte[2]; //your original array here
int len = y.Length;
unsafe
{
fixed (byte* s= y)
{
byte* source = s;
byte* dest = u.y;
for (int i = 0; i < len; i++)
{
*dest++ = *source++;
}
}
}
答案 2 :(得分:0)
在这个特定的例子中你可以这样做:
[StructLayout(LayoutKind.Explicit)]
struct byte_array
{
[FieldOffset(0)]
public byte byte1;
[FieldOffset(1)]
public byte byte2;
[FieldOffset(0)]
public short packetid;
}
但一般来说,Buffer.BlockCopy可能是更好的解决方案。
答案 3 :(得分:0)
我最终解决的是一个带有隐式转换运算符的结构,它调用了ReadByPointer方法。
public struct GenericPacket
{
public short packetid;
public static GenericPacket ReadUsingPointer(byte[] data)
{
unsafe
{
fixed (byte* packet = &data[0])
{
return *(GenericPacket*)packet;
}
}
}
static public implicit operator GenericPacket(byte[] value)
{
return GenericPacket.ReadUsingPointer(value);
}
}
这允许您执行以下操作:
GenericPacket packet = bufferFromReceive;
谢谢-jD