为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
拉莫斯之舞 2021-07-07 13:09:48
我正在寻找将 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 个项目执行此操作。就我而言,我不需要担心字节顺序,因为这已经在其他地方处理过了。
查看完整描述

1 回答

?
慕容708150

TA贡献1831条经验 获得超4个赞

这将工作,没有不安全的代码(但实际上它仍然很不安全)...... try... finally...with emptytry {}用于防止异步异常。


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

            }

        }

    }

}


查看完整回答
反对 回复 2021-07-10
  • 1 回答
  • 0 关注
  • 170 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信