このコードを考えてみましょう:
_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
でないことについて文句を言わなかった。
[〜#〜]ソリューション[〜#〜]
ジェネリックメソッドをリファクタリングして、struct
とenum
の両方で機能させることができます。
_// 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);
_
これは、列挙型に関するECMA-335の要件の違いによって課せられる制限のようです(ECMA-335 Partition II§14.3)。
...自動フィールドレイアウトが必要です(§10.1.2)。 ...
Marshal.SizeOf
への期待:
この方法は、構造がない場合に使用できます。レイアウトは順次または明示的である必要があります。
これに基づいて、Enum.GetUnderlyingType
を呼び出す前にMarshal.SizeOf
を使用する必要があります。
Marshal.SizeOf(t)
はアンマネージストラクチャを必要とし、enumはマネージストラクチャです。 。NET 列挙型の定数サイズを把握できます。
int size1 = sizeof(MyEnum);
Console.WriteLine("Enum: {0}", size1);
int size2 = Marshal.SizeOf(typeof(MyStruct));
Console.WriteLine("Struct: {0}", size2);