c# .net enums marshalling

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);