将 byte[] 转换为显式结构的最简单方法

我正在寻找将 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 个项目执行此操作。

  • 就我而言,我不需要担心字节顺序,因为这已经在其他地方处理过了。


拉莫斯之舞
浏览 177回答 1
1回答

慕容708150

这将工作,没有不安全的代码(但实际上它仍然很不安全)...... try... finally...with emptytry {}用于防止异步异常。public struct OrderStruct{&nbsp; &nbsp; public const int SIZE = 16;&nbsp; &nbsp; public int AssetId;&nbsp; &nbsp; public int OrderQty;&nbsp; &nbsp; public double Price;&nbsp; &nbsp; public static OrderStruct FromBytes(byte[] data)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (data.Length < SIZE)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new ArgumentException("Size is incorrect");&nbsp; &nbsp; &nbsp; &nbsp; GCHandle h = default(GCHandle);&nbsp; &nbsp; &nbsp; &nbsp; try&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; finally&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; h = GCHandle.Alloc(data, GCHandleType.Pinned);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OrderStruct t = Marshal.PtrToStructure<OrderStruct>(h.AddrOfPinnedObject());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return t;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; finally&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (h.IsAllocated)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; h.Free();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; public byte[] ToBytes()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var result = new byte[SIZE];&nbsp; &nbsp; &nbsp; &nbsp; GCHandle h = default(GCHandle);&nbsp; &nbsp; &nbsp; &nbsp; try&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; finally&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; h = GCHandle.Alloc(result, GCHandleType.Pinned);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Marshal.StructureToPtr(this, h.AddrOfPinnedObject(), false);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return result;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; finally&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (h.IsAllocated)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; h.Free();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP