2016-11-16 17 views
0

私はC#でC++での労働組合のようなものを宣言した:バイト配列を1回の操作で構造体構造体に変換するにはどうすればよいですか?

[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; 
} 

また、私は、私はマーカーオブジェクトに私の配列を変換する必要がサイズ5とbyte[] bytesを持っています。

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

または::私は、以下の方法でそれを行うことができますOKですが、私はパフォーマンス・ビューから、より最適な方法で行うことが可能であると考え

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回の操作で構造体に変換する方法はありますか?

答えて

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

Or演算子のオーバーロード:

[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; 
    } 
} 

どちらのソリューションは、あなたのstructワンライナーを作成するだろう:

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

これは同じです。すべての 'result.count_'x '= bytes [' y ']'には、Int32またはInt64プロセッサーコマンドが1つ使用されます。 –

+0

なぜ気になりますか?それはあなたにとって重要なパフォーマンスにとても苦しんでいますか?パフォーマンスを最適化する場合は、プロファイラを実行します。それは、CPUコマンドを気にするよりも、あなたの時間を有効に活用することになります。 – Sefe

+0

私はバイトマッピングに 'struct'と' FieldOffset'を使用しました - もちろんパフォーマンスに関するこの質問。私はプロファイラーを使用する必要はありません私はパフォーマンスの問題を参照してください(私の実際のタスクではそれが重要です)と私は解決策を見つけようとしています。私は私の質問をより明確にするために編集しました。 –

関連する問題