2013-07-26 14 views
43

Rozważmy kod:Marshal.SizeOf wyrzuca ArgumentException na teksty stałe

public enum MyEnum { V1, V2, V3 } 

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

zgłasza wyjątek:

nieobsługiwany wyjątek typu 'System.ArgumentException' w module TestConsole.exe

Dodatkowe informacje: Wpisz "TestConsole.Program + MyEnum" nie może być marszałka jako struktura niezarządzana; nie można obliczyć żadnego znaczącego rozmiaru ani przesunięcia.

Chociaż ten kod nie wyjątek i size zawiera 4:

public enum MyEnum { V1, V2, V3 } 

public struct MyStruct 
{ 
    public MyEnum en; 
} 

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

Może ktoś wyjaśnić, dlaczego NET nie może dowiedzieć się, że enum wynosi 4 bajty w pierwszej próbce kod?

UPDATE

Marshal.Sizeof() zawiodły mnie w tej metody rodzajowe:

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

i kompilator nie narzekają enum nie będąc struct.

ROZWIĄZANIE

mogłem byłaby moja metoda rodzajowa, aby pracować zarówno struct i 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); 
+2

[this] (http://stackoverflow.com/questions/4219413/c-sharp-sizeofenum-alternative-to-workaround-resharper-false-error) nie wyjaśnia, dlaczego, ale podaje obejście. –

+0

W przeciwieństwie do tego, możliwe jest utworzenie typu wskaźnika na "MyEnum", z niebezpiecznym kodem, który używa typu 'MyEnum *'. –

Odpowiedz

25

wydaje się, że ograniczenie nakładane przez różnicę między wymaganiami ECMA-335 dla teksty stałe (ECMA 335 podziału II §14.3):

... będą miały automatyczny układ pól (§10.1.2); ...

a oczekiwania Marshal.SizeOf:

Można użyć tej metody, jeśli nie mają strukturę. Układ musi być sekwencyjny lub jawny.

Na tej podstawie konieczne będzie użycie Enum.GetUnderlyingType przed wywołaniem Marshal.SizeOf.

+0

Wszystkie wyliczenia mają układ automatyczny, niezależnie od tego, czy jawnie podajesz typ bazowy. Jest to właściwość w bazowych metadanych kodu bajtowego. –

+0

Należy zauważyć, że następujący kod jest poprawny (nawet poza kontekstem "niebezpieczny") i daje oczekiwaną wartość: 'const int s = sizeof (MyEnum);'. Tak więc kompilator C# chętnie wykorzystuje "szerokość" leżącego u podstaw typu całkowego, a wyrażenie jest uważane za stałą czasu kompilacji. –

+2

Powyższa odpowiedź jest potwierdzana przez fakt, że jeśli zadeklarujemy 'struct' z parą liczb całkowitych (powiedzmy) w nim i dekorujemy strukturę struct za pomocą atrybutu' [StructLayout (LayoutKind.Auto)] ', to ta struktura zachowuje się dokładnie tak jak typ enum wrt. "rozmiar". To znaczy, że 'Marshal.SizeOf' zgłasza ten sam wyjątek, podczas gdy' sizeof (...) 'działa (ale jest dozwolony tylko w kontekście' niebezpiecznym' ponieważ ten "rozmiar" nie jest uważany za stałą czasu kompilacji). –

0

Marshal.SizeOf(t) chce mieć niezarządzanego struct, a enum jest zarządzany struct . .NET można dowiedzieć się stałą wielkość wyliczenia:

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

@ 0699 - Prawdopodobnie masz rację, ale czy masz referencje? –

+0

Dla szczególnego przypadku Enum może być [Enum.GetUnderlyingType] (http://msdn.microsoft.com/en-us/library/system.enum.getunderlyingtype.aspx) interesująca metoda – metadings

+0

Skopiuj kod z Wouter Huysentruit i odczytać wyjątek "Typ" MyEnum "nie może być skonstruowany jako struktura niezarządzana; nie można obliczyć żadnego znaczącego rozmiaru lub przesunięcia ". – 0699

Powiązane problemy