As we know System.Enum is a base for all enums, but I wonder why reflection says that it is not enum itself?
Console.WriteLine(typeof(System.Enum).IsEnum) // says it is false
I can't understand the logic, so System.Enum is not enum, but everything that derived from it is enum?
I had a second shock when I saw in msdn that it is a class
public abstract class Enum : ValueType,
IComparable, IFormattable, IConvertible
So Enum is a class, however it is value type (derived from special ValueType
class, which make enum as value type) and is base for all enums, but is not an enum itself :)
Well, if you don't believe that Enum is class, check typeof(System.Enum).IsClass
The question is: are there any reason why IsEnum
is false and IsClass
is true for a type which is value type and is base for all enums?
enum AAA { }
typeof(System.Enum).IsClass //True
typeof(System.Enum).IsEnum //False
typeof(AAA).IsClass //False
typeof(AAA).IsEnum //True
typeof(AAA).BaseType //System.Enum
IL doesn't know structs. IL only has classes.
So, what is a C# struct? It's a sealed class, that extends the System.ValueType
type. The System.ValueType
is also what determines what the IsClass
and IsStruct
properties of the Type
class return.
So why does Type.IsClass
return false? Actually quite simple. While the Type.IsClass
will really return false
for an enum, the type you get by e.g. typeof(Enum)
is not actually System.Type
- it's System.RuntimeType
. And System.RuntimeType
defines the IsValueTypeImpl
method a bit differently:
return !(this == typeof(ValueType))
&& !(this == typeof(Enum))
&& this.IsSubclassOf(typeof(ValueType));
So there's an explicit extra check - the Enum
type itself, while deriving from ValueType
, an thus semantically a struct
, is actually classified as not value-type.
But the individual Enum types derived from System.Enum
are also subclasses of ValueType
, and aren't the special case of System.Enum
, so they register as not classes.
All in all, do not assume that things that are true for C# also hold for .NET at large. And of course, don't assume that the high-level abstractions still hold in practice - technically, .NET is 100% object oriented, with a single "master" System.Object
on top of the class hierarchy. Even System.ValueType
extends (has to) System.Object
. But - value types are not actually System.Object
; when you cast them to System.Object
, you're creating a new object, which wraps the actual value type.
Just like value types in general, .NETs enum
s are "ugly hacks". They're a special thing as far as the runtime (and a lot of the internal .NET code) is considered, and they're there to simplify things for you as the programmer, or to improve performance (and security, and safety, and ...).
In the end, as you've discovered, some things have to be inconsistent. Enum
derives from ValueType
. As per C# semantics, it should be a struct
. But you can't extend a struct
! And yet, that's what you actually want to do in this case.
I suspect that if enums were to be added to .NET in (say) 5.0, they would be implemented differently. Perhaps just an IEnum
interface and a couple of extension methods. But extension methods weren't there in C# 1.0, and for value types, they would impose unnecessary performance penalties.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With