47

考虑这段代码:

public enum MyEnum { V1, V2, V3 }

int size = Marshal.SizeOf(typeof(MyEnum));

它抛出异常:

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

谁能解释为什么 .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);
4

2 回答 2

29

这似乎是由 ECMA-335 对枚举的要求之间的差异所施加的限制(ECMA-335 Partition II §14.3):

...它们应具有自动字段布局(第 10.1.2 节);...

和期望Marshal.SizeOf

当您没有结构时,您可以使用此方法。布局必须是顺序的或显式的。

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

于 2013-07-26T12:34:12.733 回答
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);
于 2013-07-26T11:35:12.653 回答