如何通过一次操作将字节数组转换为union结构?

时间:2016-11-16 10:05:13

标签: c# struct type-conversion byte union

我在C#中声明类似于C ++中的union:

[StructLayout(LayoutKind.Explicit, Size = 5)]
public struct Marker
{
        [FieldOffset(0)] public byte label;
        [FieldOffset(1)] public int count;

        [FieldOffset(1)] private byte count_0;
        [FieldOffset(2)] private byte count_1;
        [FieldOffset(3)] private byte count_2;
        [FieldOffset(4)] private byte count_3;
}

此外,我的byte[] bytes大小为5.我需要将我的数组转换为Marker对象。我可以通过以下方式实现:

var marker = new Marker 
{
    label = bytes[0],
    count = BitConverter.ToInt32(bytes, 1)
}

或者:

var marker = new Marker 
{
    label = bytes[0],
    count_0 = bytes[1],
    count_1 = bytes[2],
    count_2 = bytes[3],
    count_3 = bytes[4]
}

没关系,但我认为可以通过更优化的方式从性能视图开始 - 只需将marker指向bytes的第一个字节。我试图找到这样的东西:

BitConverter.To<Marker>(bytes);

如何通过一次操作将字节数组转换为union结构?

2 个答案:

答案 0 :(得分:1)

这应该有效

    static void Main(string[] args)
    {
        //Creating test data
        List<byte> data = new List<byte>();
        data.Add(123);
        data.AddRange(BitConverter.GetBytes((int)123456));

        //Converting test data to Struct
        Marker m = StructFromBytes<Marker>(data.ToArray());

        //Check if it works
        Console.WriteLine(m.label); //Prints 123
        Console.WriteLine(m.count); //Prints 123456
    }

    private static T StructFromBytes<T>(byte[] bytes)
    {
        int structSize = Marshal.SizeOf(typeof(T));
        byte[] structBytes = new byte[structSize];
        Array.Copy(bytes, 0, structBytes, 0, structSize);

        GCHandle handle = GCHandle.Alloc(structBytes, GCHandleType.Pinned);
        T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
        handle.Free();

        return theStructure;
    }

答案 1 :(得分:0)

您可以创建构造函数:

[StructLayout(LayoutKind.Explicit, Size = 5)]
public struct Marker
{
    [FieldOffset(0)] public byte label;
    [FieldOffset(1)] public int count;

    [FieldOffset(1)] private byte count_0;
    [FieldOffset(2)] private byte count_1;
    [FieldOffset(3)] private byte count_2;
    [FieldOffset(4)] private byte count_3;

    public Marker(byte[] bytes)
    {
       label = bytes[0];
       count_0 = bytes[1];
       count_1 = bytes[2];
       count_2 = bytes[3];
       count_3 = bytes[4];
    }
}

或运算符重载:

[StructLayout(LayoutKind.Explicit, Size = 5)]
public struct Marker
{
    [FieldOffset(0)] public byte label;
    [FieldOffset(1)] public int count;

    [FieldOffset(1)] private byte count_0;
    [FieldOffset(2)] private byte count_1;
    [FieldOffset(3)] private byte count_2;
    [FieldOffset(4)] private byte count_3;

    public static explicit operator Marker(byte[] bytes)
    {
       Marker result = new Marker();
       result.label = bytes[0];
       result.count_0 = bytes[1];
       result.count_1 = bytes[2];
       result.count_2 = bytes[3];
       result.count_3 = bytes[4];
       return result;
    }
}

这两种解决方案都可以使您的结构创建一个单行:

Marker marker = new Marker(bytes);
Marker marker = (Marker)bytes;