Question

Test if an object is an Enum discusses testing an object with is Enum to see if it contains an enum value.

Is this specified anywhere in the spec? The entry on is (7.10.10 in Version 4.0) lists the following possible right-hand values:

  • anonymous function
  • method group
  • null
  • reference type ** This might be an enum?
  • nullable type
  • non-nullable value type ** This might be an enum?

Assuming that an enum value matches "reference type" from the list above - the spec states as follows:

...the result is true if D [the dynamic type of the RHS)] and T [the LHS] are the same type, if D is a reference type and an implicit reference conversion from D to T exists, or if D is a value type and a boxing conversion from D to T exists.

Are any of these conditions strictly true in the case of is Enum? There is no compiler support for, say, is class or is struct.

So is the support for is Enum according to the specification, or is it an implementation decision?

Was it helpful?

Solution

There is no support for is class or is struct, because there is no common base type that would differentiate classes or structs from other types. is Enum works, because System.Enum is an actual type that is the base of all enums. And Enum is a reference type, so the last part applies:

if D is a value type and a boxing conversion from D to T exists

D (the type of the expression on the left side) is a value type. And T is Enum, which is a base type of D. So there is a boxing conversion from D to Enum and so the value of the expression is true.

The boxing conversion from any enum to Enum is specified explicitly in §14.4 The System.Enum type:

The type System.Enum is the abstract base class of all enum types (this is distinct and different from the underlying type of the enum type), and the members inherited from System.Enum are available in any enum type. A boxing conversion exists from any enum type to System.Enum, and an unboxing conversion exists from System.Enum to any enum type.

Note that System.Enum is not itself an enum-type. Rather, it is a class-type from which all enum-types are derived. The type System.Enum inherits from the type System.ValueType, which, in turn, inherits from type object. At run-time, a value of type System.Enum can be null or a reference to a boxed value of any enum type.

OTHER TIPS

Enum is a reference type.

typeof(Enum).IsValueType => false

Interestingly,

typeof(ValueType).IsValueType => false

Enum is an actual type where as class and struct are not. Therefore, Enum can be used on the right-hand side where as class and struct cannot.

What is being asked here has not been entirely clear to me but I hope I got it now.


Given the code below:

void F(Object obj) {
  var isEnum obj is Enum;
  ...
}

What parts of the C# standard specifies that isEnum is true when obj is an instance of an enum type?


In 14.9.10 is operator in the C# Language Specification there are five bullets describing how it is evaluated:

  • The 1st bullet is about cases where obj has a more specific type than System.Object.

  • The 2nd bullet is about nullable types.

  • The 4th bullet is about generic types.

  • The 5th bullet is when there are no matches and the is operator evaluates to false which we know it doesn't.

You would expect that the 3rd bullet applies to the code above. The 3rd bullet has four sub-bullets:

  • The 1st sub-bullet applies when obj is null.

  • The 2nd sub-bullet is about nullable types.

  • The 4th sub-bullet is when there are no matches and the is operator evaluates to false which we know it doesn't.

You would expect the the 3rd sub-bullet applies:

Otherwise, let R be the run-time type of the instance referenced by e. If R and T are the same type, if R is a reference type and an implicit reference conversion from R to T exists, or if R is a value type and T is an interface type that is implemented by R, the result is true.

However, there seems to be something specific about enum types missing here. Assuming obj is an instance of enum type MyEnum none of the clauses matches the code above:

  • R and T are not the same type because R is MyEnum and T is System.Enum.

  • R is MyEnum which is a value type (11.1.9) and not a reference type.

  • T is System.Enum which is not an interface type.

I don't want to claim that there is an error in the specification, but after a detailed reading of 14.9.10 I'm unable to see how is Enum can evaluate to true given a boxed reference to an enum type.

Knowing that standards people in general are much smarter than I am I probably overlooked something, but even if I didn't this shouldn't stop you from using is Enum to test if a type is an enum. I'm sure that it is not an implementation detail that it can used like this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top