How would I approach your example and similar ones in complexity, I would first ask myself if the structure can be reduced to one primitive type. If possible, I would simply hide the fixed buffer inside the structure through access to the property or indexer.
In your example, you had the following.
struct s1 { byte _b1; byte _b2; } unsafe struct s2 { fixed s1 _s1[5];
What I could consider if I decided that I absolutely needed structures to be combined into one continuous data block is something like this.
[StructLayout(LayoutKind.Explicit, Size = 2)] struct s1 { // Field offsets to emulate union style access which makes it // simple to get at the raw data in a primitive type format. [FieldOffset(0)]ushort _u1; [FieldOffset(0)]byte _b1; [FieldOffset(1)]byte _b2; public s1(ushort data) { _b1 = 0; _b2 = 0; _u1 = data; } public ushort ToUShort() { return _u1; } } unsafe struct s2 { public const int Size = 5; private fixed ushort _s1[Size]; public s1 this[int index] { // A public indexer that provides the data in a friendlier format. get { if (index < 0 || index >= Size ) throw new IndexOutOfRangeException(); return new s1(_s1[index]); } set { if (index < 0 || index >= Size) throw new IndexOutOfRangeException(); _s1[index] = value.ToUShort(); } } }
If it looks like a hack, then because it's kind of like. I would not recommend this as a general solution, because it is difficult to maintain, but in those rare cases when you work at such a low level and know in advance that the data specification will not change, then something like this method may be viable. But even in these cases, I would still prefer to encapsulate as much as possible of such a low level to minimize the likelihood that something will go wrong. However, this does exactly as required, for a workaround to having a fixed buffer size of user structures.
source share