2016-11-16 41 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'進行字節映射 - 當然這個問題關於性能。我不需要使用性能分析器,我會看到性能問題(在我的真實任務中它很關鍵),我正在努力尋找解決方案。我編輯了我的問題以便更清楚。 –

相關問題