C # implementation of Union,
I. Basics
Unlike C ++, C # Does not Union itself, but can be implemented by manually controlling the position of each element of the struct.StructLayoutAttribute, LayoutKind, and FieldOffsetAttribute. When using them, the System. Runtime. InteropServices must be referenced. below is the union of simulation u I wrote.
[StructLayout(LayoutKind.Explicit, Size = 4)]struct U{ [FieldOffset(0)] public byte b0; [FieldOffset(1)] public byte b1; [FieldOffset(2)] public byte b2; [FieldOffset(3)] public byte b3; [FieldOffset(0)] public int i; [FieldOffset(0)] public float f;}
We know that every data member in the Union starts at the same memory address, so we need to apply it to every member of U through [FieldOffset (0, this means that these members are in the same starting position. Of course, we have to tell you in advance. the memory layout of these members is determined by us, so we need to use LayoutKind. the Explicit enumeration is passed to StructLayoutAttribute and applied to U. net will no longer interfere with the layout of the struct members in the memory. And I have defined the Size of U as 12. Of course, you can also not define the Size of U.
In addition, using the Union for data conversion is faster than BitConverter. The test cases are as follows:
{ DateTime past = DateTime.Now; int length = 500000 * 3 * 3; for (int i = 0; i < length; i++) { U a = new U(); a.b0 = 0xFF; a.b1 = 0xFF; int res = a.i; } DateTime now = DateTime.Now; Console.WriteLine((now - past));} { DateTime past = DateTime.Now; int length = 500000 * 3 * 3; for (int i = 0; i < length; i++) { byte[] a = { 0xFF, 0x0F, 0x0F, 0 }; object b = a; int res = BitConverter.ToInt32(a, 0); } DateTime now = DateTime.Now; Console.WriteLine((now - past));}
Ii. Advanced
There are still many problems with the previous method. For example, if the array cannot be put into the Union, a message indicating a value conflict with the reference is displayed.
Today I have studied how to use the pointer feature in C #, combined with unsafe and fixed,Coexistence of array type and common value type.
Method ① coexistence of array type and common value type -- fixed size buffer zone
The fixed-size buffer (fixed) is used to realize the coexistence of array and common value types.
[StructLayoutAttribute(LayoutKind.Explicit, Pack = 1)]public unsafe struct A{ [FieldOffset(0)] public int a; [FieldOffset(0)] public byte b; [FieldOffset(0)] public float c; [FieldOffset(0)] public fixed byte arr[9];};
Method ② convert struct to byte array -- 1). Use Union 2). Use Pointer to force conversion
1 ). use a consortium to use a fixed byte buff [n] with the same length as the original struct. This buff is the direct array we want. During access, we need to use fixed (byte * ta =. buff.
[StructLayoutAttribute(LayoutKind.Explicit, Pack = 1)]public unsafe struct A{ [FieldOffset(0)] public int a; [FieldOffset(4)] public byte b; [FieldOffset(5)] public float c; [FieldOffset(0)] public fixed byte buff[9];};
2) directly use the pointer for forced conversion. With fixed, convert the struct to void * first, and then convert it to byte * B.
fixed (void * ta = &a){ byte* b = (byte*)ta ;}
3). Finally, copy the data to the C # standard byte [] Using IntPtr.
byte[] Dbuff = new byte[9];IntPtr pstart = new IntPtr(a);Marshal.Copy(pstart, Dbuff, 0, 9);