Самый простой способ конвертировать byte [] в явную структуру - PullRequest
0 голосов
/ 29 мая 2018

Я ищу самый простой способ преобразования байта [] в структуру.Мои тесты показывают, что это работает:

[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 Ответ

0 голосов
/ 29 мая 2018

Это будет работать без небезопасного кода (но на самом деле это все еще довольно небезопасно) ... try... finally... с пустым try {} предназначены для защиты от асинхронных исключений.

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