将 byte[] 转换为显式结构的最简单方法
Easiest way to convert byte[] to an explicit struct
我正在寻找将 byte[] 转换为结构的最直接方法。我的测试表明这有效:
[StructLayout(LayoutKind.Explicit, Size = OrderStruct.SIZE)]
public unsafe struct OrderStruct
{
public const int SIZE = 16;
[FieldOffset(0)]
private fixed byte _data[OrderStruct.SIZE];
[FieldOffset(0), MarshalAs(UnmanagedType.I4)]
public int AssetId;
[FieldOffset(4), MarshalAs(UnmanagedType.I4)]
public int OrderQty;
[FieldOffset(8), MarshalAs(UnmanagedType.R8)]
public double Price;
public static OrderStruct FromBytes(ref byte[] data)
{
if (data.Length < SIZE)
throw new ArgumentException("Size is incorrect");
OrderStruct t = default(OrderStruct);
fixed (byte* src = data)
{
Buffer.MemoryCopy(src, t._data, SIZE, SIZE);
}
return t;
}
public byte[] ToBytes()
{
var result = new byte[SIZE];
fixed (byte* dst = result)
fixed (byte* src = this._data)
{
Buffer.MemoryCopy(src, dst, result.Length, SIZE);
}
return result;
}
}
我是不是遗漏了一个边缘案例,或者这是解决这个问题的好方法吗?
附加信息:
- 性能很重要,否则我会用 BitConverter 单独转换每个项目,这个解决方案明显更快。
- 我真的不需要通用解决方案,因为我只会对我的代码库中的 1 或 2 个项目执行此操作。
- 就我而言,我不需要担心字节顺序,因为其他地方已经处理过了。
这将有效,没有不安全的代码(但实际上它仍然很不安全)...带空 try {}
的 try... finally...
用于防止异步异常。
public struct OrderStruct
{
public const int SIZE = 16;
public int AssetId;
public int OrderQty;
public double Price;
public static OrderStruct FromBytes(byte[] data)
{
if (data.Length < SIZE)
throw new ArgumentException("Size is incorrect");
GCHandle h = default(GCHandle);
try
{
try
{
}
finally
{
h = GCHandle.Alloc(data, GCHandleType.Pinned);
}
OrderStruct t = Marshal.PtrToStructure<OrderStruct>(h.AddrOfPinnedObject());
return t;
}
finally
{
if (h.IsAllocated)
{
h.Free();
}
}
}
public byte[] ToBytes()
{
var result = new byte[SIZE];
GCHandle h = default(GCHandle);
try
{
try
{
}
finally
{
h = GCHandle.Alloc(result, GCHandleType.Pinned);
}
Marshal.StructureToPtr(this, h.AddrOfPinnedObject(), false);
return result;
}
finally
{
if (h.IsAllocated)
{
h.Free();
}
}
}
}
我正在寻找将 byte[] 转换为结构的最直接方法。我的测试表明这有效:
[StructLayout(LayoutKind.Explicit, Size = OrderStruct.SIZE)]
public unsafe struct OrderStruct
{
public const int SIZE = 16;
[FieldOffset(0)]
private fixed byte _data[OrderStruct.SIZE];
[FieldOffset(0), MarshalAs(UnmanagedType.I4)]
public int AssetId;
[FieldOffset(4), MarshalAs(UnmanagedType.I4)]
public int OrderQty;
[FieldOffset(8), MarshalAs(UnmanagedType.R8)]
public double Price;
public static OrderStruct FromBytes(ref byte[] data)
{
if (data.Length < SIZE)
throw new ArgumentException("Size is incorrect");
OrderStruct t = default(OrderStruct);
fixed (byte* src = data)
{
Buffer.MemoryCopy(src, t._data, SIZE, SIZE);
}
return t;
}
public byte[] ToBytes()
{
var result = new byte[SIZE];
fixed (byte* dst = result)
fixed (byte* src = this._data)
{
Buffer.MemoryCopy(src, dst, result.Length, SIZE);
}
return result;
}
}
我是不是遗漏了一个边缘案例,或者这是解决这个问题的好方法吗?
附加信息:
- 性能很重要,否则我会用 BitConverter 单独转换每个项目,这个解决方案明显更快。
- 我真的不需要通用解决方案,因为我只会对我的代码库中的 1 或 2 个项目执行此操作。
- 就我而言,我不需要担心字节顺序,因为其他地方已经处理过了。
这将有效,没有不安全的代码(但实际上它仍然很不安全)...带空 try {}
的 try... finally...
用于防止异步异常。
public struct OrderStruct
{
public const int SIZE = 16;
public int AssetId;
public int OrderQty;
public double Price;
public static OrderStruct FromBytes(byte[] data)
{
if (data.Length < SIZE)
throw new ArgumentException("Size is incorrect");
GCHandle h = default(GCHandle);
try
{
try
{
}
finally
{
h = GCHandle.Alloc(data, GCHandleType.Pinned);
}
OrderStruct t = Marshal.PtrToStructure<OrderStruct>(h.AddrOfPinnedObject());
return t;
}
finally
{
if (h.IsAllocated)
{
h.Free();
}
}
}
public byte[] ToBytes()
{
var result = new byte[SIZE];
GCHandle h = default(GCHandle);
try
{
try
{
}
finally
{
h = GCHandle.Alloc(result, GCHandleType.Pinned);
}
Marshal.StructureToPtr(this, h.AddrOfPinnedObject(), false);
return result;
}
finally
{
if (h.IsAllocated)
{
h.Free();
}
}
}
}