System.Enum - not a class?
-
Type.GetType("System.Enum").IsClass returns false, yet all the documentation indicates that System.Enum is a class. What am I missing?
-
Type.GetType("System.Enum").IsClass returns false, yet all the documentation indicates that System.Enum is a class. What am I missing?
You're not missing anything, it's just that the documentation isn't very consistent in the use of definitions.
IsClass
is false, asSystem.Enum
inherits fromValueType
. You needn't instantiate an enum, like you would do with a 'real' class.An enumeration is a named constant whose underlying type is any integral type except Char. If no underlying type is explicitly declared, Int32 is used. Programming languages typically provide syntax to declare an enumeration that consists of a set of named constants and their values. Enum provides methods to compare instances of this class, convert the value of an instance to its string representation, convert the string representation of a number to an instance of this class, and create an instance of a specified enumeration and value.
It's the phrase "provides methods to compare instances of this class" that makes it harder to explain. You don't make (
new
) instances of an enum, you assign it's value to avalueType
. Alas, the thing that you are assigning is an instance of a valuetype. See, speech is mainly for communication and not for the errorless movement of ideas. That's why lots of casual talk is misinterpreted, as both sender and receiver use different versions of the definition of the data that is transmitted :) Ehr.. ..the short answer was that an enumeration is not a class :-\I are troll :)
-
You're not missing anything, it's just that the documentation isn't very consistent in the use of definitions.
IsClass
is false, asSystem.Enum
inherits fromValueType
. You needn't instantiate an enum, like you would do with a 'real' class.An enumeration is a named constant whose underlying type is any integral type except Char. If no underlying type is explicitly declared, Int32 is used. Programming languages typically provide syntax to declare an enumeration that consists of a set of named constants and their values. Enum provides methods to compare instances of this class, convert the value of an instance to its string representation, convert the string representation of a number to an instance of this class, and create an instance of a specified enumeration and value.
It's the phrase "provides methods to compare instances of this class" that makes it harder to explain. You don't make (
new
) instances of an enum, you assign it's value to avalueType
. Alas, the thing that you are assigning is an instance of a valuetype. See, speech is mainly for communication and not for the errorless movement of ideas. That's why lots of casual talk is misinterpreted, as both sender and receiver use different versions of the definition of the data that is transmitted :) Ehr.. ..the short answer was that an enumeration is not a class :-\I are troll :)
MSDN also wrote (on the same page you cited):
C#
[SerializableAttribute]
[ComVisibleAttribute(true)]
public abstract class Enum : ValueType, IComparable, IFormattable, IConvertibleWhen I right-click on Enum in a source window in VS and choose Go To Definition it also indicates it's a class:
using System.Runtime.InteropServices;
namespace System
{
// Summary:
// Provides the base class for enumerations.
[Serializable]
[ComVisible(true)]
public abstract class Enum : ValueType, IComparable, IFormattable, IConvertible
{
members snipped ...
}
}The Object Browser in Visual Studio isn't sure what it is. Sometimes it thinks it's a struct and sometimes an abstract class. The bottom line? I'm still not convinced one way of the other.
-
MSDN also wrote (on the same page you cited):
C#
[SerializableAttribute]
[ComVisibleAttribute(true)]
public abstract class Enum : ValueType, IComparable, IFormattable, IConvertibleWhen I right-click on Enum in a source window in VS and choose Go To Definition it also indicates it's a class:
using System.Runtime.InteropServices;
namespace System
{
// Summary:
// Provides the base class for enumerations.
[Serializable]
[ComVisible(true)]
public abstract class Enum : ValueType, IComparable, IFormattable, IConvertible
{
members snipped ...
}
}The Object Browser in Visual Studio isn't sure what it is. Sometimes it thinks it's a struct and sometimes an abstract class. The bottom line? I'm still not convinced one way of the other.
It seems that there's indeed an abstract class for working with the structs. If you declare an enum, you're actually inserting named numbers;
MSDN wrote:
An enumeration is a named constant whose underlying type is any integral type except Char.
..and then I ran into this post[^] from Brad Abrams, stating that both
System.Enum
andSystem.ValueType
are implemented as reference-types. If I understood it correctly, then there's a difference between the abstractSystem.Enum
class and the declared enum that is based on a underlying type?I are troll :)
-
Type.GetType("System.Enum").IsClass returns false, yet all the documentation indicates that System.Enum is a class. What am I missing?
System.Enum is a value type class. "IsClass Gets a value indicating whether the Type is a class; that is, not a value type or interface. "[^] It's probably just not a very good name for the property, but most developers are too lazy to type
IsNeitherValueTypeNorInterface
. Object is a class, everything derives from object, therefore everything is a class, but some classes are "special" classes. I don't think you'd want every type to return true, what good would that be? -
System.Enum is a value type class. "IsClass Gets a value indicating whether the Type is a class; that is, not a value type or interface. "[^] It's probably just not a very good name for the property, but most developers are too lazy to type
IsNeitherValueTypeNorInterface
. Object is a class, everything derives from object, therefore everything is a class, but some classes are "special" classes. I don't think you'd want every type to return true, what good would that be?OK. Given that
System.Enum
is declared aspublic abstract class Enum : ValueType, IComparable, IFormattable, IConvertible
, in your opinion, what should the following return?Type.GetType("System.Enum").IsClass
Type.GetType("System.Enum").IsInterface
Type.GetType("System.Enum").IsValueTypeMy guess would be true, false, false when the reality is false, false, false. As far as I can tell,
Enum
is the only type declared as a class in theSystem
namespace hierarchy whereType.GetType("type name").IsClass
returns false. I'm trying to find out why, and nothing I've read so far has answered that question. BTW, not everything derives fromObject
. Interfaces do not derive from anything. -
OK. Given that
System.Enum
is declared aspublic abstract class Enum : ValueType, IComparable, IFormattable, IConvertible
, in your opinion, what should the following return?Type.GetType("System.Enum").IsClass
Type.GetType("System.Enum").IsInterface
Type.GetType("System.Enum").IsValueTypeMy guess would be true, false, false when the reality is false, false, false. As far as I can tell,
Enum
is the only type declared as a class in theSystem
namespace hierarchy whereType.GetType("type name").IsClass
returns false. I'm trying to find out why, and nothing I've read so far has answered that question. BTW, not everything derives fromObject
. Interfaces do not derive from anything.Adrian Cole wrote:
I'm trying to find out why, and nothing I've read so far has answered that question.
We've already answered that. All value types return false for IsClass, just as the documentation specifies; that's why. Anyone can write a class that derives from ValueType and it will do the same thing, there just aren't that many times where you want a value type that isn't a structure. Enum is one such case because it also has to be abstract, there's no way to make an abstract structure, so they made it an abstract value type class.
-
Adrian Cole wrote:
I'm trying to find out why, and nothing I've read so far has answered that question.
We've already answered that. All value types return false for IsClass, just as the documentation specifies; that's why. Anyone can write a class that derives from ValueType and it will do the same thing, there just aren't that many times where you want a value type that isn't a structure. Enum is one such case because it also has to be abstract, there's no way to make an abstract structure, so they made it an abstract value type class.
Yeah, I guess I was just too stubborn to have it sink in. For those that care, creating a class that derives from System.ValueType isn't allowed ... 'TestNamespace.TestClass' cannot derive from special class 'System.ValueType'.
-
MSDN also wrote (on the same page you cited):
C#
[SerializableAttribute]
[ComVisibleAttribute(true)]
public abstract class Enum : ValueType, IComparable, IFormattable, IConvertibleWhen I right-click on Enum in a source window in VS and choose Go To Definition it also indicates it's a class:
using System.Runtime.InteropServices;
namespace System
{
// Summary:
// Provides the base class for enumerations.
[Serializable]
[ComVisible(true)]
public abstract class Enum : ValueType, IComparable, IFormattable, IConvertible
{
members snipped ...
}
}The Object Browser in Visual Studio isn't sure what it is. Sometimes it thinks it's a struct and sometimes an abstract class. The bottom line? I'm still not convinced one way of the other.
I think enum values are treated like boxed ints by default, although IIRC it's possible to use other types for the values. Whatever it is there's runtime type information available to know what enum type the value belongs to. And we're allowed to cast between enums in the somewhat optimistic hope that their underlying values correspond. This much can be shown by running the following simple application (requires you to create a new windows forms app and drop a button on the form and wire up the click event, as I don't include the designer.cs file here).
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}enum en { Zero, One, Two, Three }; enum fr { Nul, Un, Deux, Trois }; void foo(object obj) { if (obj is en) dbug("en:{0} => fr:{1}", obj, (fr)obj); else if (obj is fr) dbug("fr:{0} => en:{1}", obj, (en)obj); else dbug("?:{0} => en:{1}, fr:{2}", obj, (en)obj, (fr)obj); } void dbug(string s, params object\[\] args) { if (args.Length > 0) s = string.Format(s, args); Debug.WriteLine(s); } void button1\_Click(object sender, EventArgs e) { Random r = new Random(); for (int i = 0; i < 20; i++) { object v = r.Next(4); if (r.Next(100) < 33) foo((en)v); else if (r.Next(100) < 50) foo((fr)v); else foo(v); Thread.Sleep(500); } }
}