Marshal.SizeOf在枚举上抛出ArgumentException

时间:2013-07-26 11:09:08

标签: c# .net enums marshalling

考虑以下代码:

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

2 个答案:

答案 0 :(得分:25)

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

  

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

Marshal.SizeOf的期望:

  

如果没有结构,可以使用此方法。布局必须是顺序的或明确的。

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

答案 1 :(得分:0)

Marshal.SizeOf(t)确实想拥有一个非托管结构,而一个枚举是一个托管结构。 .NET可以计算枚举的常量大小:

int size1 = sizeof(MyEnum);
Console.WriteLine("Enum: {0}", size1);
int size2 = Marshal.SizeOf(typeof(MyStruct));
Console.WriteLine("Struct: {0}", size2);