Array Covariance Among Enums
Cyrus, developer of C# at Microsoft, posted a quiz on casting arrays of value types.
He hasn't posted the answer to the quiz yet, but I already knew the answer, which highlights an important difference between the way the CLR and the C# compiler treats enumerated constants. From the perspective of the CLR and IL, enums are mostly indistinguishable from regular integers. This lack of distinction is even more pronounced with arrays of enums.
Array covariance is widely known to be supported for reference types, but it also works on enumerated types. Direct conversion from an array of enums to an array of integers (and vice-versa) is disallowed by the C# compiler. However, by first casting an array of enums to the Array type and then to an array of integers, the identity conversion succeeds.
int array = (int) (Array) new IntEnum;
IntEnum1 array2 = (YEnum) (Array) new IntEnum2;
This indirect conversion also works between two arrays of different enumerated types, provided the underlying integer type is the same. The CLR actually returns true for IsInstanceOfType and IsAssignableFrom in the following cases:
- typeof( int ).IsInstanceOfType( new intEnum )) —> true
- typeof( intEnum ).IsInstanceOfType( new int )) —> true
- typeof( intEnum1 ).IsInstanceOfType( new intEnum2 )) —> true
- typeof( int ).IsAssignableFrom( typeof( intEnum )) —> true
- typeof( intEnum ).IsAssignableFrom( typeof( int )) —> true
However, the C# will return false at compile time with a warning if the “is” operator is used. Precasting the array to the Array type before using the “is” operator, though, will produce the same behavior as the runtime.
Except for the element type returned by Type.GetElementType() for arrays, arrays of enumerated types and arrays of integers are treated identically. Also, unlike covariance for reference types, there is no performance hit from type checking.