2016-11-16 38 views
0

我在C#中类似工会在C++中声明:如何通过一个操作将字节数组转换为联合结构?

[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,我需要我的数组来标记对象转换。

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] 
} 

这是确定的,但我认为这是可以通过更优化的方式从性能视图做的事情 - 只是点到的第一个字节bytes。我试图找到这样的事情:

BitConverter.To<Marker>(bytes); 

如何通过一个操作字节数组转换为工会结构?

回答

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; 
    } 
+0

如果表现是你的问题,那将会适得其反。固定你的数据并编组它应该比分配数值更耗时。 – Sefe

+0

如果你想要性能,我会使用像C++这样的语言。 –

+0

他在问题中说他想要最佳表现。 Interop不会是要走的路... – Sefe

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; 
+0

这是一样的。对于每个'result.count_'x'= bytes ['y']',将使用一个Int32或Int64处理器命令。 –

+0

你为什么在意?你对表现如此敏感以至于对你很重要?如果您想优化性能,请运行一个分析器。与担心CPU命令相比,这将更好地利用您的时间。 – Sefe

+0

我使用'struct'和'FieldOffset'进行字节映射 - 当然这个问题关于性能。我不需要使用性能分析器,我会看到性能问题(在我的真实任务中它很关键),我正在努力寻找解决方案。我编辑了我的问题以便更清楚。 –

相关问题