C#中结构体和字节数组转换

方式一

 通过Marshal实现结构体和字节数组之间的转换。

using System;
using System.Runtime.InteropServices;

namespace MarshalSample
{
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    struct Message
    {
        public ushort begin;
        [MarshalAs(UnmanagedType.U1)]
        public bool result;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
        public byte[] detail;
        public ushort end;
    };

    class Program
    {
        public static byte[] StructToBytes(T obj)
        {
            int size = Marshal.SizeOf();
            byte[] bytes = new byte[size];
            IntPtr ptr = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(obj, ptr, false);
            Marshal.Copy(ptr, bytes, 0, size);
            Marshal.FreeHGlobal(ptr);

            return bytes;
        }

        public static T BytesToStruct(byte[] bytes)
        {
            int size = Marshal.SizeOf();
            if (bytes.Length < size)
            {
                return default(T);
            }

            IntPtr ptr = Marshal.AllocHGlobal(size);
            Marshal.Copy(bytes, 0, ptr, size);
            T obj = Marshal.PtrToStructure(ptr);
            Marshal.FreeHGlobal(ptr);

            return obj;
        }

        static void Main(string[] args)
        {
            Message msg;
            msg.begin = 0xF9F9;
            msg.result = true;
            msg.detail = new byte[2] { 0x00, 0x00 };
            msg.end = 0x9F9F;

            byte[] bytes = StructToBytes(msg);
            Message newMsg = BytesToStruct(bytes);
        }
    }
}

方式二

通过MemoryMarshal实现结构体和字节数组之间的转换。

using System;
using System.Runtime.InteropServices;

namespace MarshalSample
{
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    struct Message
    {
        public ushort begin;
        [MarshalAs(UnmanagedType.U1)]
        public bool result;
        //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
        //public byte[] detail;
        public ushort end;
    };

    class Program
    {
        public static byte[] StructToBytes(T obj) where T : struct
        {
            int size = Marshal.SizeOf();
            byte[] bytes = new byte[size];

            T value = (T)obj;
            MemoryMarshal.Write(bytes.AsSpan(), ref value);

            return bytes;
        }

        public static T BytesToStruct(byte[] bytes) where T : struct
        {
            int size = Marshal.SizeOf();
            if (bytes.Length < size)
            {
                return default(T);
            }

            var obj = MemoryMarshal.Read(bytes);

            return obj;
        }

        static void Main(string[] args)
        {
            Message msg;
            msg.begin = 0xF9F9;
            msg.result = true;
            //msg.detail = new byte[2] { 0x00, 0x00 };
            msg.end = 0x9F9F;

            byte[] bytes = StructToBytes(msg);
            Message newMsg = BytesToStruct(bytes);
        }
    }
}

MemoryMarshal的使用有限制,结构体中不能包含指针和引用。如果打开代码中的注释后,运行时会抛出异常。详细见Microsoft文档中的说明:

public static T Read (ReadOnlySpan source) where T : struct;
public static void Write (Span destination, ref T value) where T : struct;

Remarks
T cannot contain pointers or references. It is checked at runtime in order to preserve type safety.

参考:

C#中结构体定义并转换字节数组 - bigfan - 博客园

C#结构体使用bool类型,并使其长度为1_sdhongjun的专栏-CSDN博客

C# Marshal.SizeOf和sizeof的区别_Sakuya__的博客-CSDN博客_c# marshal.sizeof

你可能感兴趣的:(Windows,Programming,c#,开发语言)