Và bây giờ cho một cái gì đó hoàn toàn khác nhau ...
này không thực sự trả lời câu hỏi của OP; thay vào đó nó là thứ mà tôi đã nấu chín để cung cấp một cách ánh xạ một cấu trúc C# trên một mảng byte và cho phép các trường riêng lẻ trong mảng byte cơ bản được đọc và ghi. Nó sử dụng mã không an toàn, và nhận được một con trỏ đến mảng byte và sau đó phôi nó vào một con trỏ đến cấu trúc ánh xạ các trường.
Điều này có thể không hiệu quả lắm, nhưng có lợi thế là cung cấp ánh xạ biểu tượng của các trường mà không sử dụng "số ma thuật" cho độ dài và độ lệch của trường. Nhưng lưu ý rằng điều này sẽ không làm việc cho trao đổi dữ liệu với một hệ thống sử dụng lớn endian thay vì ít đại diện dữ liệu endian.
Các phương thức truy cập trường được triển khai dưới dạng phương thức mở rộng. Xem TestMethod() để biết ví dụ về cách sử dụng chúng.
Điều này được lấy cảm hứng từ câu trả lời của Christopher Currens - nếu bạn thấy điều này hữu ích, hãy cho anh ấy một bài viết.
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
unsafe struct ExampleStruct
{
internal const int CField4Length = 18;
public UInt64 Field1;
public UInt32 Field2;
public UInt16 Field3;
public fixed byte Field4[CField4Length];
}
static unsafe class ExampleStructExtensionMethods
{
public static UInt64 GetField1(this byte[] byteArray)
{
fixed (byte* byteArrayPointer = &byteArray[0])
{
return (*(ExampleStruct*)byteArrayPointer).Field1;
}
}
public static UInt32 GetField2(this byte[] byteArray)
{
fixed (byte* byteArrayPointer = &byteArray[0])
{
return (*(ExampleStruct*)byteArrayPointer).Field2;
}
}
public static UInt16 GetField3(this byte[] byteArray)
{
fixed (byte* byteArrayPointer = &byteArray[0])
{
return (*(ExampleStruct*)byteArrayPointer).Field3;
}
}
public static byte[] GetField4(this byte[] byteArray)
{
fixed (byte* byteArrayPointer = &byteArray[0])
{
byte[] field4 = new byte[ExampleStruct.CField4Length];
for (int i = 0; i < ExampleStruct.CField4Length; i++)
field4[i] = (*(ExampleStruct*)byteArrayPointer).Field4[i];
return field4;
}
}
public static void SetField1(this byte[] byteArray, UInt64 field1)
{
fixed (byte* byteArrayPointer = &byteArray[0])
{
(*(ExampleStruct*)byteArrayPointer).Field1 = field1;
}
}
public static void SetField2(this byte[] byteArray, UInt32 field2)
{
fixed (byte* byteArrayPointer = &byteArray[0])
{
(*(ExampleStruct*)byteArrayPointer).Field2 = field2;
}
}
public static void SetField3(this byte[] byteArray, UInt16 field3)
{
fixed (byte* byteArrayPointer = &byteArray[0])
{
(*(ExampleStruct*)byteArrayPointer).Field3 = field3;
}
}
public static void SetField4(this byte[] byteArray, byte[] field4)
{
if (field4.Length != ExampleStruct.CField4Length)
throw new ArgumentException("Byte array must have length 18", "field4");
fixed (byte* byteArrayPointer = &byteArray[0])
{
for (int i = 0; i < ExampleStruct.CField4Length; i++)
(*(ExampleStruct*)byteArrayPointer).Field4[i] = field4[i];
}
}
}
class TestProgram
{
byte[] exampleData =
{
// These 8 bytes should go in 'field1'
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
// These 4 bytes should go in 'field2'
0x08,0x09,0x0A,0x0B,
// These 2 bytes should go in 'field3'
0x0C,0x0D,
// These 18 * 1 bytes should go in 'field4'
0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
};
public void TestMethod()
{
UInt64 field1 = exampleData.GetField1();
UInt32 field2 = exampleData.GetField2();
UInt16 field3 = exampleData.GetField3();
byte[] field4 = exampleData.GetField4();
exampleData.SetField1(++field1);
exampleData.SetField2(++field2);
exampleData.SetField3(++field3);
exampleData.SetField4(new byte[ExampleStruct.CField4Length]
{ 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42 });
}
}
}
Điều quan trọng cần biết là từ khóa cố định chỉ có thể được sử dụng trong ngữ cảnh không an toàn. Cố định theo nghĩa đen có nghĩa là trường này thực sự thuộc kiểu 'byte *' thay vì một byte []. –
@Christopher - điều này là chính xác, thậm chí nó có thể cần một công cụ sửa đổi không an toàn cho phần khai báo stuct. Tôi đã không thử và biên dịch mã này. – Hogan