Marshal.SizeOf在枚举上抛出ArgumentException
考虑这个代码:
public enum MyEnum { V1, V2, V3 } int size = Marshal.SizeOf(typeof(MyEnum));
它抛出exception:
TestConsole.exe中出现未处理的“System.ArgumentException”typesexception
附加信息:types'TestConsole.Program + MyEnum'不能作为非托pipe结构编组; 没有意义的大小或偏移量可以计算出来。
虽然这段代码不会抛出exception,但size
包含4:
public enum MyEnum { V1, V2, V3 } public struct MyStruct { public MyEnum en; } int size = Marshal.SizeOf(typeof(MyStruct));
任何人都可以解释为什么.NET框架不能找出第一个示例代码中的enum
是4字节?
UPDATE
Marshal.Sizeof()
在这个generics方法中失败了:
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); } }
而编译器没有抱怨enum
不是一个struct
。
解
我可以重构我的generics方法,使其工作的struct
和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);
这似乎是ECMA-335对于枚举的要求(ECMA-335分割II第14.3节)之间的差异所施加的限制:
…他们应该有自动场布局(§10.1.2); …
Marshal.SizeOf
的期望:
当你没有结构时,你可以使用这个方法。 布局必须是顺序的或明确的。
基于此,您需要在调用Marshal.SizeOf
之前使用Enum.GetUnderlyingType
。
Marshal.SizeOf(t)
确实希望有一个非托pipe结构,而枚举是一个托pipe结构。 .NET可以计算一个枚举的常量大小:
int size1 = sizeof(MyEnum); Console.WriteLine("Enum: {0}", size1); int size2 = Marshal.SizeOf(typeof(MyStruct)); Console.WriteLine("Struct: {0}", size2);