c# - Marshal.SizeOf lanza ArgumentException en enumeraciones
.net enums (2)
Considere este código:
public enum MyEnum { V1, V2, V3 }
int size = Marshal.SizeOf(typeof(MyEnum));
lanza la excepción:
Se produjo una excepción no controlada del tipo ''System.ArgumentException'' en TestConsole.exe
Información adicional: el tipo ''TestConsole.Program + MyEnum'' no se puede calcular como una estructura no administrada; No se puede calcular ningún tamaño significativo o desplazamiento.
Si bien este código no arroja una excepción y el size
contiene 4:
public enum MyEnum { V1, V2, V3 }
public struct MyStruct
{
public MyEnum en;
}
int size = Marshal.SizeOf(typeof(MyStruct));
¿Alguien puede explicar por qué .NET Framework no puede darse cuenta de que la enum
es de 4 bytes en el primer código de muestra?
ACTUALIZAR
Marshal.Sizeof()
me falló en este método genérico:
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);
}
}
Y el compilador no se quejó de que la enum
no es una struct
.
SOLUCIÓN
Podría refactorizar mi método genérico para que funcione tanto para struct
como para 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);
Esto parece ser una limitación impuesta por una diferencia entre los requisitos de ECMA-335 para las enumeraciones (ECMA-335 Partition II §14.3):
... tendrán un diseño de campo automático (§10.1.2); ...
Y las expectativas de Marshal.SizeOf
:
Puedes usar este método cuando no tienes una estructura. El diseño debe ser secuencial o explícito.
En función de esto, deberá utilizar Enum.GetUnderlyingType
antes de llamar a Marshal.SizeOf
.
Marshal.SizeOf(t)
desea tener una estructura no administrada, y una enumeración es una estructura administrada. .NET puede calcular el tamaño constante de una enumeración:
int size1 = sizeof(MyEnum);
Console.WriteLine("Enum: {0}", size1);
int size2 = Marshal.SizeOf(typeof(MyStruct));
Console.WriteLine("Struct: {0}", size2);