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

解决方案

我可以重构我的通用方法,使其同时适用于structenum:

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

Marshal.SizeOf在枚举上引发ArgumentException

这似乎是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);