6

Apparently there's a list of blittable types and so far I don't see Enums specifically on it. Are they blittable in general? Or does it depend on whether they are declared with a blittable base type?

//e.g.
internal enum SERVERCALL : uint
{
    IsHandled = 0,
    Rejected = 1,
    RetryLater = 2,
}

References exhausted:

4 Answers 4

7

Enums are blittable types. From the enum keyword documentation:

Every enumeration type has an underlying type, which can be any integral type except char.

Because the underlying type is integral (all of which are on the list of blittable types), the enum is also blittable.

0
7

Enum types themselves are not blittable (since they do not have counterpart in unmanaged world) but the values are.

3
  • 3
    This should be the answer. Commented Aug 9, 2017 at 20:43
  • Nitpick counterproposal: enum types are blittable, WHEN its values have the same representation in managed memory, as unmanaged memory, which is ALWAYS, ASSUMING that you defined the underlying enum type correctly to match the size of the unmanaged type, and the actual values of the enum also match those defined for the unmanaged code. Commented Jan 8, 2019 at 0:25
  • What difference is there between types being blittable and values being blittable anyway? I would suppose we should say that a type is blittable only if its size is the same, and all its values are blittable. I.e. the interpretation of particular values in memory by managed code and unmanaged code must be the same. Commented Jul 7, 2020 at 5:06
4

Aliostad is correct. For example, if one tries to execute the statement:

int size = Marshal.SizeOf( System.ConsoleColor.Red );

then an ArgumentException is thrown, with the message:

Type 'System.ConsoleColor' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.

However, the statement:

int size = Marshal.SizeOf( (int)System.ConsoleColor.Red );

works just fine as one would expect.

Likewise, the statement:

int enumSize = Marshal.SizeOf( typeof(ConsoleColor) );

fails, but the statement:

int enumSize = Marshal.SizeOf( Enum.GetUnderlyingType( typeof(ConsoleColor) ) );

succeeds.

Unfortunately, Microsoft's documentation for Marshal.SizeOf( object ) is deficient; that page doesn't even include ArgumentException in the list of possible exceptions. The doc for Marshal.SizeOf( Type ) lists ArgumentException, but only says that it's thrown when the type is generic (which is true, but doesn't cover the above example).

(Also, the documentation for the enum keyword, the Enum class, and Enumeration Types in the C# Programming Guide makes no mention at all about whether an enum value is directly blittable.)

2
  • 1
    Interesting answer, but I'm not sure that you have proved the enum to be blittable or not, all you have proven is that Marshal.SizeOf doesn't like enums? Commented Jun 7, 2013 at 22:49
  • Interestingly, this works: [Serializable] public enum MyConsoleColor : int { White = 0, Red = 1, Green = 2, } [StructLayout(LayoutKind.Sequential)] public struct MyStruct { public MyConsoleColor c; } static void Main(string[] args) { int t1 = Marshal.SizeOf(typeof(MyStruct)); int t2 = Marshal.SizeOf(new MyStruct { c = MyConsoleColor.White }); } Commented Jun 7, 2013 at 22:49
0

instead of

int enumSize = Marshal.SizeOf(Enum.GetUnderlyingType(typeof(ConsoleColor)));

you can write

int enumSize = Marshal.SizeOf(typeof(ConsoleColor).GetEnumUnderlyingType());

actually the first one calls the second one...

Not the answer you're looking for? Browse other questions tagged or ask your own question.