For test purpose, I want to compare two structs (of unknown type T) marshaled from unmanaged code.
Because they may contain some packing in unmanaged representation, it is inappropriate to convert whole struct to byte array and then compare byte by byte:
int size = Marshal.SizeOf(typeof(T));
IntPtr buf1 = Marshal.AllocHGlobal(size); // FreeHGlobal omitted for simplicity
IntPtr buf2 = Marshal.AllocHGlobal(size);
byte[] array1 = new byte[size];
byte[] array2 = new byte[size];
Marshal.StructureToPtr(st1, buf1, false);
Marshal.StructureToPtr(st2, buf2, false);
Marshal.Copy(buf1, array1, 0, size);
Marshal.Copy(buf2, array2, 0, size);
// inapropriate
for (int i = 0; i < size; ++i)
{
if (array1[i] != array2[i]) { return false; }
}
return true;
I think it is necessary to compare field by field.
Thanks to reflection, I can enumerate FieldInfo, and then using Marshal.OffsetOf method I can get offsets of the fields.
Unfortunately, however, I have no idea how to get sizes of the fields. Without it I think I can't compare two fields eliminating the effect of packing.
foreach (var fieldInfo in typeof(T).GetFields())
{
int offset = (int)Marshal.OffsetOf(typeof(T), fieldInfo.Name);
int fieldSize = ...; // I need this
for (int i = offset; i < offset + fieldSize; ++i)
{
if (array1[i] != array2[i]) { return false; }
}
}
return true;
Is there any way to accomplish this? Or Is there better way to compare the unmanaged structs?
Note: Field types are arbitrary (may be primitive integers, arrays, strings, enums, structs, etc).