I posted a related question a few weeks ago : Marshal.Sizeof() returning unexpected value
As background, we hired a third party to convert an old C++ project to C#. This is a communications protocol application that sends/receives messages over ethernet, where all messages contain payloads that are serialized representations of defined structures:
typedef struct // size=10
{
ushort group;
ushort line;
ushort v_group;
byte ip_address[4];
}GROUP_T;
typedef struct // size=91
{
byte struct_version;
ushort region_id;
byte address[8];
GROUP_T groups[8];
} LCT_T;
These were converted to C# classes:
[Serializable]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class GROUP_T
{
public ushort group;
public ushort line;
public ushort v_group;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U1)]
public byte[] ip_address = new byte[4];
}
[Serializable]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class LCT_T
{
public byte struct_version;
public ushort region_id;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] address = new byte[8];
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
public byte[] group_config_bytes = new byte[80];
}
My problem is with the group_config_bytes element of the LCT_T class. Programmatically this works, but the original array of GROUP_T structs was lost to the equivalent byte array (originally, the GROUP_T array was empty and unused). Now I need to set values for individual GROUP_T objects, so I need the nested-array-of-classes version:
[Serializable]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class LCT_T
{
public byte struct_version;
public ushort region_id;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] address = new byte[8];
[MarshalAs(UnmanagedType.ByValArray, ArraySubType=UnmanagedType.Struct,SizeConst = 10)]
public GROUP_T[] groups = new GROUP_T[8];
}
This compiles, but Marshal.SizeOf(typeof(LCT_T)) is returning the wrong size (should be 11 + (8 * 10) = 91).
Without this updated LCT_T class definition, if I need to set elements of individual groups, I have to poke values directly into group_config_bytes , which is ugly, prone to errors, and unclear to future maintainers of this code.
So: what's the right way to define nested arrays of classes within a class?