web-dev-qa-db-ja.com

Marshal.SizeOfが列挙型でArgumentExceptionをスローする

このコードを考えてみましょう:

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

また、コンパイラはenumstructでないことについて文句を言わなかった。

[〜#〜]ソリューション[〜#〜]

ジェネリックメソッドをリファクタリングして、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);
_
45
huysentruitw

これは、列挙型に関するECMA-335の要件の違いによって課せられる制限のようです(ECMA-335 Partition II§14.3)。

...自動フィールドレイアウトが必要です(§10.1.2)。 ...

Marshal.SizeOfへの期待:

この方法は、構造がない場合に使用できます。レイアウトは順次または明示的である必要があります。

これに基づいて、Enum.GetUnderlyingTypeを呼び出す前にMarshal.SizeOfを使用する必要があります。

26
Sam Harwell

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