Marshal.SizeOf在枚举上引发ArgumentException
本文关键字:ArgumentException 枚举 SizeOf Marshal | 更新日期: 2023-09-27 18:24:58
考虑以下代码:
public enum MyEnum { V1, V2, V3 }
int size = Marshal.SizeOf(typeof(MyEnum));
它抛出了一个异常:
中发生类型为"System.ArgumentException"的未处理异常TestConsole.exe
附加信息:类型"TestConsole.Program+MyEnum"不能为作为非托管结构封送;没有任何有意义的大小或偏移可以计算。
虽然此代码没有抛出异常,并且size
包含4:
public enum MyEnum { V1, V2, V3 }
public struct MyStruct
{
public MyEnum en;
}
int size = Marshal.SizeOf(typeof(MyStruct));
有人能解释为什么.NET框架在第一个示例代码中不能计算出enum
是4个字节吗?
更新
Marshal.Sizeof()
在以下通用方法中对我失败:
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
。
解决方案
我可以重构我的通用方法,使其同时适用于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)
确实希望具有非托管结构,而枚举是托管结构。NET可以计算出枚举的常量大小:
int size1 = sizeof(MyEnum);
Console.WriteLine("Enum: {0}", size1);
int size2 = Marshal.SizeOf(typeof(MyStruct));
Console.WriteLine("Struct: {0}", size2);