固定对象到字节数组

SF *_*per 7 c# bytearray

我有一个简单的对象,如下所示:

public class Foo
{
   public UInt32 One { get; set; }
   public UInt32 Two { get; set; }
   public UInt32 Three { get; set; }
   public UInt32 Four { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我尝试了这个代码,我发现网上的某个地方:

public byte[] ObjectToByteArray(Object obj)
{
    MemoryStream fs = new MemoryStream();
    BinaryFormatter formatter = new BinaryFormatter();
    formatter.Serialize(fs, obj);
    byte[] rval = fs.ToArray();
    fs.Close();
    return rval;
}
Run Code Online (Sandbox Code Playgroud)

但不知何故,返回的字节数组的大小为248字节.
我希望它是4字节x 4字段= 16字节.

问题:
将固定对象转换为字节数组的最简洁方法是什么?
在这种情况下,结果数组的大小应该是16个字节吗?

Ato*_*osk 6

BinaryFormatter保存了许多类型信息,以便能够正确反序列化.如果你想要紧凑的序列化或通过一些严格的协议进行通信,你将必须明确地这样做:

public byte[] ToByteArray()
{
    List<byte> result = new List<byte>();

    result.AddRange(BitConverter.GetBytes(One));
    result.AddRange(BitConverter.GetBytes(Two));
    result.AddRange(BitConverter.GetBytes(Three));
    result.AddRange(BitConverter.GetBytes(Four));

    return result.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

在这里,我将每个UInt32转换为字节数组并将其存储在结果数组中.

编辑
结果有另一种方法,使用structMarshal 首先你struct用这样的属性制作和标记它:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct MyStruct
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
    public string StringField;

    public int IntField;
}
Run Code Online (Sandbox Code Playgroud)

这里LayoutKind.Sequential告诉clr将内存中的字段保存为与声明相同的顺序.没有Pack = 1结构可以占用比所需更多的内存.struct与一个short字段一样,一个字段byte只需要3个字节,但默认情况下它的大小很可能是4(处理器有操作单字节,2字节和4字节的指令,clr牺牲每个struct实例一个字节来减少指令量机器代码减半).现在您可以Marshal用来复制字节:

public static byte[] GetBytes<T>(T str)
{
    int size = Marshal.SizeOf(str);
    var bytes = new byte[size];
    IntPtr ptr = Marshal.AllocHGlobal(size);

    try 
    {
         Marshal.StructureToPtr(str, ptr, true);
         Marshal.Copy(ptr, bytes, 0, size);
         return bytes;
    }
    finally 
    {
         Marshal.FreeHGlobal(ptr);
    }
}
Run Code Online (Sandbox Code Playgroud)

简单类型的一切都很好.对于复杂类型,例如string你必须使用MarshalAs属性,它的使用有点复杂(例如我告诉clr将字符串编组为固定的50字节大小的数组).