Enums inheritance

Topics: C# Language Design
May 16, 2014 at 11:25 PM
Edited May 16, 2014 at 11:27 PM
It would be useful to have some kind of inheritance for enums. I am aware that enum is considered to be a value type but it is still a special kind of it. Example:
public enum MyObjectKind
{
  Type1,
  Type2,
}

public enum MySpecialObjectKind : MyObjectKind
{
  Type3,
  Type4,
}
The syntax might clash with current base-type option but it is still feasible. Splitting derived enum types into different assemblies can have similar behavior as constants. The base enum type(s) members values are copied into the assembly where the derived enum type is declared. Actually it creates single enum type MySpecialObjectKind that have four members.
May 16, 2014 at 11:41 PM
I wish this had been built into the type system, since it would certainly be useful. Unfortunately, I'm not sure how much the type system can deviate from saying that all value types must derive directly from either System.ValueType or System.Enum without breaking a lot of code.
May 22, 2014 at 8:41 PM
Edited May 22, 2014 at 9:04 PM
It is still valid.The enumeration types actually can not use the same inheritance logic (polymorfism) as classes. Lets try to picture it:

both MyObjectKind and MySpecialObjectKind are derived directly from System.Enum, the MySpecialObjectKind has four flat members, two taken from MyObjectKind and rest two from itself.

The MySpecialObjectKind can not act as replacement of MyObjectKind because contains extra Type3 and Type4 members while MyObjectKind can act as MySpecialObjectKind because have common two members Type1 and Type2. The logic is reversed to the class inheritance and thus some extra IL metadata would be required to describe the relation between MyObjectKind and MySpecialObjectKind. Reflection can take the extra metadata information into the acount when logically describing types and the CLR rule of direct inheritance from System.Enum is still kept. A bit messy solution ? Yes, maybe still better than nothing.
May 23, 2014 at 1:57 AM
pvones wrote:
It is still valid.The enumeration types actually can not use the same inheritance logic (polymorfism) as classes. Lets try to picture it:

both MyObjectKind and MySpecialObjectKind are derived directly from System.Enum, the MySpecialObjectKind has four flat members, two taken from MyObjectKind and rest two from itself.

The MySpecialObjectKind can not act as replacement of MyObjectKind because contains extra Type3 and Type4 members while MyObjectKind can act as MySpecialObjectKind because have common two members Type1 and Type2.
Every enum has an associated numeric type (often Int32), and will be capable of storing any value of that type. Any enumerated type may be converted to any other which is backed by the same numeric type if the value is first cast to the numeric type. Thus, in terms of low-level type safety, all enumerated types which are backed by an Int32 could be considered interchangeable.

From a semantic standpoint, for non-flags enum values, code which expects a particular enumerated type will often not do anything particularly useful if given a value which does not have a defined label. "Flags" enumerations, however, are another story. What would perhaps be most helpful would be if each flags enum type could define a bitmask which was reserved for its own use, and types which derived from a flags enum were limited to claiming bits that were not used by the parent. Such a design could allow safe conversions among related types if upcasting [required to be explicit] would mask off bits that were unused in the parent type. If two derived types use the lower 8 bits the same way, but differ in the meaning of upper bits, a variable of one derived type could be upcast to its parent (stripping off all but the lower 8 bits), and then passed to a method expecting the other (which would regard all the upper-bit options as being unset).

I think such types could be supported by a compiler, while using the existing runtime, by having a pair of set of generic structure types (one for each integer size) whose type parameter would be required to satisfy a new constraint and implement a special interface for fetching the bitmask and bit labels [an instance created with new would be expected to supply information about the flags enumeration type]. The necessary (but presently lacking) compiler feature to make it work would be a means of defining generic conversion operators between generic types--an ability that is presently unavailable.

Flags enumerations should be, but aren't, a very efficient and extensible way for objects to specify information about abilities. In some cases, abilities should have multiple flags for conditions which are almost opposite, but could both be false [e.g. IsImmutable and IsMutable--an object might not know of any way by which it can be mutated, but not be certain that no means could possibly exist; requiring a separate bool property for every flag would create a strong disincentive toward accurately describing objects' abilities, but using a flags type could allow many abilities to be described by a single method that returns a 32-bit or 64-bit value.