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