C# 如何将值结构的数组转换为字节?

C# 如何将值结构的数组转换为字节?,c#,.net,serialization,binary,C#,.net,Serialization,Binary,我有一个值结构类型的System.Array,如下所示: public value struct Position { int timestamp; float x; float y; } Position[] positions = new Position[1000 * 1000]; 在我用值初始化数组之后,我如何才能获得它的内容的字节[],而不一次序列化一个项目 在C++/CLI中,我将使用pin_ptr获取指向数组内容的指针,并从中复制数据。我可以用C#做这样

我有一个值结构类型的
System.Array
,如下所示:

public value struct Position
{
    int timestamp;
    float x;
    float y;
}

Position[] positions = new Position[1000 * 1000];
在我用值初始化数组之后,我如何才能获得它的内容的
字节[]
,而不一次序列化一个项目

在C++/CLI中,我将使用
pin_ptr
获取指向数组内容的指针,并从中复制数据。我可以用C#做这样的事吗

编辑:我需要将原始数据写入磁盘,就像它是一个C结构一样,没有任何序列化

我将这个问题标记为C#,以便更广泛地公开,但实际上我正在尝试序列化IronPython中的数据,因此这意味着我不能使用任何不安全的C#功能。

也许这会有帮助:

[Serializable()]
    public struct Position
    {
        int timestamp;
        float x;
        float y;
    }


    static void Main(string[] args)
    {
        var positions = new Position[1000 * 1000];
        GetBytes(positions);
    }
    private static byte[] GetBytes(object obj)
    {
        using (var memoryStream = new System.IO.MemoryStream())
        {
            var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            binaryFormatter.Serialize(memoryStream, obj);
            return memoryStream.ToArray();
        }
    }

我认为这相当于使用不安全C代码的C++/CLI pin#ptr:


以下是一种不需要不安全代码的方法:

[更新以删除for循环并在一次过程中执行复制]

private static byte[] StructureToByteArray(Position[] posArray)
{
    if (posArray == null || posArray.Length == 0)
    {
        return new byte[0];
    }

    var lenOfObject = Marshal.SizeOf(typeof(Position));
    var len = lenOfObject * posArray.Length;
    var arr = new byte[len];

    var handle = GCHandle.Alloc(posArray, GCHandleType.Pinned);
    try
    {
        var ptr = handle.AddrOfPinnedObject();
        Marshal.Copy(ptr, arr, 0, len);
    }
    finally
    {
        handle.Free();
    }

    return arr;
}

Convert.GetBytes()
不工作吗?复制:@Default:如果您指的是
BitConverter.GetBytes
,则不工作。它返回一个
byte[]
,内部只有一个字节。您打算如何处理生成的字节数组?您需要将其存储在数据库中、发送到web服务还是???了解这一点可能有助于我们找到合适的解决方案。@competent_-tech:我已经更新了描述。我不认为
序列化
格式化程序返回原始数据。这种方法确实提供了一个字节数组,并且只需要很少的编码工作,所以我认为这是完全正确的答案。当然,生成的字节数组不会尽可能小,因为它确实包含一些用于反序列化的类型信息。这取决于个人来决定是否适合他们的需要。我只是认为使用标准包I C#比使用不安全代码更好。我还认为,序列化对象时必须保存类型信息,这是事实。因此,字节数组可能更大,但我认为标准解决方案是更可取的。是否有必要将带有LayoutKind的StructLayout属性(顺序或显式)应用于Position结构,以便可靠地使用此方法?只是想知道。谢谢,但我不能用不安全的。我已经更新了说明,说明了原因。@Wily博士的徒弟,如果您要尝试与需要特定二进制布局的非托管代码进行互操作,我绝对建议您使用显式布局。我不确定自动布局定位的保证有多强。问题与不安全的答案相同:如果使用这种方法,将
StructLayout
属性和
LayoutKind
Sequential
Explicit
应用于
位置
struct是否是一个好主意,或者这无关紧要?最好指定
LayoutKind.Sequential
。由于结构经常用于互操作,因此它是C#/VB.NET编译器(可能还有其他编译器)的默认值,但不能保证它会保持不变。这贯穿于每一项。我想避免这种情况。
private static byte[] StructureToByteArray(Position[] posArray)
{
    if (posArray == null || posArray.Length == 0)
    {
        return new byte[0];
    }

    var lenOfObject = Marshal.SizeOf(typeof(Position));
    var len = lenOfObject * posArray.Length;
    var arr = new byte[len];

    var handle = GCHandle.Alloc(posArray, GCHandleType.Pinned);
    try
    {
        var ptr = handle.AddrOfPinnedObject();
        Marshal.Copy(ptr, arr, 0, len);
    }
    finally
    {
        handle.Free();
    }

    return arr;
}