Considérez ce code:
public enum MyEnum { V1, V2, V3 }
int size = Marshal.SizeOf(typeof(MyEnum));
il lève l'exception:
Une exception non gérée de type "System.ArgumentException" s'est produite dans TestConsole.exe
Informations supplémentaires: Le type "TestConsole.Program + MyEnum" ne peut pas être marshalé en tant que structure non gérée; aucune taille ou décalage significatif ne peut être calculé.
Bien que ce code ne lève pas d'exception et que size
en contienne 4:
public enum MyEnum { V1, V2, V3 }
public struct MyStruct
{
public MyEnum en;
}
int size = Marshal.SizeOf(typeof(MyStruct));
Quelqu'un peut-il expliquer pourquoi le framework .NET ne peut pas comprendre que enum
est de 4 octets dans le premier exemple de code?
MISE À JOUR
Marshal.Sizeof()
a échoué sur moi dans cette méthode générique:
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);
}
}
Et le compilateur ne s'est pas plaint du fait que enum
n'était pas un struct
.
SOLUTION
Je pourrais refactoriser ma méthode générique pour qu'elle fonctionne à la fois pour struct
et 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);
Cela semble être une limitation imposée par une différence entre les exigences de l'ECMA-335 pour les énumérations (ECMA-335 Partition II §14.3):
... ils doivent avoir une disposition de champ automatique (§10.1.2); ...
Et les attentes de Marshal.SizeOf
:
Vous pouvez utiliser cette méthode lorsque vous n'avez pas de structure. La mise en page doit être séquentielle ou explicite.
Sur cette base, vous devrez utiliser Enum.GetUnderlyingType
avant d'appeler Marshal.SizeOf
.
Marshal.SizeOf(t)
veut avoir une structure non managée, et une énumération est une structure gérée. . NET peut déterminer la taille constante d'une énumération:
int size1 = sizeof(MyEnum);
Console.WriteLine("Enum: {0}", size1);
int size2 = Marshal.SizeOf(typeof(MyStruct));
Console.WriteLine("Struct: {0}", size2);