Consider this code:
public enum MyEnum { V1, V2, V3 }
int size = Marshal.SizeOf(typeof(MyEnum));
it throws the exception:
An unhandled exception of type 'System.ArgumentException' occurred in TestConsole.exe
Additional information: Type 'TestConsole.Program+MyEnum' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
While this code doesn't throw an exception and size
contains 4:
public enum MyEnum { V1, V2, V3 }
public struct MyStruct
{
public MyEnum en;
}
int size = Marshal.SizeOf(typeof(MyStruct));
Can anyone explain why the .NET framework can't figure out that the enum
is 4 bytes in the first sample code?
UPDATE
Marshal.Sizeof()
failed on me in this generic method:
public bool IoControlReadExact<T>(uint ioControlCode, out T output) where T : struct
{
output = new T();
int outBufferSize = Marshal.SizeOf(typeof(T));
IntPtr outBuffer = Marshal.AllocHGlobal(outBufferSize);
if (outBuffer == IntPtr.Zero)
return false;
try
{
uint bytesReturned;
return IoControlRead(ioControlCode, outBuffer, (uint)outBufferSize, out bytesReturned) && ((uint)outBufferSize == bytesReturned);
}
finally
{
output = (T)Marshal.PtrToStructure(outBuffer, typeof(T));
Marshal.FreeHGlobal(outBuffer);
}
}
And the compiler didn't complain about enum
not being a struct
.
SOLUTION
I could refactor my generic method to make it work for both struct
and enum
:
// determine the correct output type:
Type outputType = typeof(T).IsEnum ? Enum.GetUnderlyingType(typeof(T)) : typeof(T);
//...
int outBufferSize = Marshal.SizeOf(outputType);
//...
output = (T)Marshal.PtrToStructure(outBuffer, outputType);
This appears to be a limitation imposed by a difference between the requirements of ECMA-335 for enums (ECMA-335 Partition II §14.3):
...they shall have auto field layout (§10.1.2); ...
And the expectations of Marshal.SizeOf
:
You can use this method when you do not have a structure. The layout must be sequential or explicit.
Based on this, you will need to use Enum.GetUnderlyingType
before calling Marshal.SizeOf
.