Marshal.SizeOf在枚举上抛出ArgumentException

huy*_*itw 45 .net c# enums marshalling

考虑以下代码:

public enum MyEnum { V1, V2, V3 }

int size = Marshal.SizeOf(typeof(MyEnum));
Run Code Online (Sandbox Code Playgroud)

它抛出异常:

TestConsole.exe中发生了未处理的"System.ArgumentException"类型异常

附加信息:类型'TestConsole.Program + MyEnum'不能作为非托管结构封送; 不能计算有意义的大小或偏移量.

虽然此代码不会抛出异常并size包含4:

public enum MyEnum { V1, V2, V3 }

public struct MyStruct
{
    public MyEnum en;
}

int size = Marshal.SizeOf(typeof(MyStruct));
Run Code Online (Sandbox Code Playgroud)

谁能解释为什么.NET框架无法弄清楚enum第一个示例代码中是4个字节?

UPDATE

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

并且编译器没有抱怨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);
Run Code Online (Sandbox Code Playgroud)

Sam*_*ell 26

这似乎是ECMA-335对枚举的要求之间的差异(ECMA-335 PartitionII§14.3):

......他们应该有自动场布局(§10.1.2); ...

和期望Marshal.SizeOf:

如果没有结构,可以使用此方法.布局必须是顺序的或显式的.

基于此,您需要Enum.GetUnderlyingType在调用之前使用Marshal.SizeOf.

  • 如果我们在其中声明一个带有几个整数字段(例如)的`struct`,并使用`[StructLayout(LayoutKind.Auto)]`属性修饰结构,那么这个结构的行为就完全证实了上面的答案.像枚举类型一样."大小".那就是`Marshal.SizeOf`抛出相同的异常,而`sizeof(...)`有效(但只允许在'unsafe`上下文中,因为这个"大小"不被认为是编译时常量). (2认同)