C# Marshal.SizeOf在枚举上引发ArgumentException

C# Marshal.SizeOf在枚举上引发ArgumentException,c#,.net,enums,marshalling,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

考虑以下代码:

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 framework不能在第一个示例代码中找出
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);
    }
}
Marshal.SizeOf(t)
不希望具有非托管结构,而枚举是托管结构。可以计算枚举的常量大小:

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

这似乎是ECMA-335对枚举的要求(ECMA-335第二部分§14.3)之间的差异造成的限制:

…它们应具有自动现场布局(§10.1.2)

以及对Marshal.SizeOf的期望:

当没有结构时,可以使用此方法。布局必须是连续的或明确的


基于此,您需要在调用
封送处理之前使用
Enum.getUnderlineType
。SizeOf
没有解释原因,但提供了一种解决方法。相反,可以创建指向
MyEnum
的指针类型,其中包含不安全的代码,也就是说,使用类型
MyEnum*
。对于枚举的特殊情况,可能存在感兴趣的方法从Wouter Huysentruit复制代码并读取异常“type'MyEnum'不能作为非托管结构封送;无法计算任何有意义的大小或偏移量。'Enum不是结构,正如System.Int32不是结构一样,即使它是这样声明的。仅当值类型值已装箱时,此类声明才相关。无论是否显式指定基础类型,所有枚举都具有自动布局。它是基础字节码元数据中的一个属性。请注意,以下代码是有效的(即使在
不安全的
上下文之外),并给出了预期值:
const int s=sizeof(MyEnum)。因此,C#编译器乐于使用基础整数类型的“宽度”,表达式被视为编译时常数。如果我们声明一个
struct
,其中包含两个整型字段(比如),并用
[StructLayout(LayoutKind.Auto)]
属性装饰结构,上述答案就得到了证实,然后,此结构的行为与枚举类型wrt完全相同。“尺寸”。也就是说,
Marshal.SizeOf
抛出相同的异常,而
SizeOf(…)
工作(但只允许在
不安全的
上下文中使用,因为此“大小”不被视为编译时常量)。Marshal.SizeOf很快将支持枚举
int size1 = sizeof(MyEnum);
Console.WriteLine("Enum: {0}", size1);
int size2 = Marshal.SizeOf(typeof(MyStruct));
Console.WriteLine("Struct: {0}", size2);