C# 将字节数组编组到结构

C# Marshal byte array to struct

我为我的问题找到了很多答案,而且它们都有效。我的问题是它们在速度和内存方面是否都相同。我怎么知道什么更快并且使用更少的内存。我通常不使用 Marshal 和 GCHandle 类。所以我完全是绿色的。

public static object RawDeserializer(byte[] rawData, int position, Type anyType)
        {
            int rawsize = Marshal.SizeOf(anyType);
            if (rawsize > rawData.Length)
                return null;
            IntPtr buffer = Marshal.AllocHGlobal(rawsize);
            Marshal.Copy(rawData, position, buffer, rawsize);
            object retobj = Marshal.PtrToStructure(buffer, anyType);
            Marshal.FreeHGlobal(buffer);
            return retobj;
        }

public static T RawDeserializer<T>(byte[] rawData, int position = 0)
        {
            int rawsize = Marshal.SizeOf(typeof(T));
            if (rawsize > rawData.Length)
            {
                throw new DataMisalignedException("byte array is not the correct size for the requested type");
            }
            IntPtr buffer = Marshal.AllocHGlobal(rawsize);
            Marshal.Copy(rawData, position, buffer, rawsize);
            T retobj = (T)Marshal.PtrToStructure(buffer, typeof(T));
            Marshal.FreeHGlobal(buffer);
            return retobj;
        }


public static T RawDeserializer<T>(byte[] bytes) where T : struct
        {
            T stuff;
            GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
            try
            {
                stuff = Marshal.PtrToStructure<T>(handle.AddrOfPinnedObject());
            }
            finally
            {
                handle.Free();
            }
            return stuff;
        }

我从所有 3 种实现中都得到了想要的结果。

第一个和第二个几乎相同:不同之处在于您没有拆箱(转换为 T:struct)第一个示例中的结果,我假设您稍后会拆箱。

第三个选项不会将内存复制到非托管堆,它只是将其固定在托管堆中,所以我认为它会分配更少的内存并且会更快。不过,我并不假装自己是真实的黄金来源,所以就去对这些选项进行性能测试吧:) BenchmarkDotNet 是一个很好的性能测试框架,可能会对你有很大帮助。

还有第三个选项可以更简洁:

public static unsafe T RawDeserializer<T>(byte[] bytes) where T : struct
{
    fixed (byte* p = bytes)
         return Marshal.PtrToStructure<T>((IntPtr)p);
}

您需要更改项目设置以允许不安全的代码:

为了不完全是绿色,我强烈建议阅读一本书 CLR via C#,第 21 章 'The Managed Heap and Garbage Collection'。