Polymorphic enums in C# ?

Using Java as a inspiration source for C# (hmm wait, hasn’t that already been done from the start ?)

A few weeks ago, I read this post by @cyriux, describing how you could use polymorphic enums in Java. Actually, I had already heard him telling that enums in C# were nothing like the ones in Java. And even if he’s sometimes trolling, he’s really got a point there. Then I thought to myself : I know I won’t be able to add this syntax to C#, because I can’t change the compiler, but how clause could I get to polymorphic enums ? Let’s try that…

First, what are the common characteristics of an enum ?

enums bind together a scalar value and a string representation, so enums can be converted to and parsed from strings

for the same reason, enums can be casted to and from scalar values (int, long, short…),

enums should be immutable (in fact, unless you introduce some mutable state in them, they already are),

enums cannot be extended by other types : once defined, their set of values is closed and cannot be modified.

I haven’t checked for Java, but here are some other characteristics of C# enums :

Enums in C# don’t have an Ordinal property, but I’ll introduce one, so that I can write unit tests as close as possible as @cyriux’s ones. It will look a little bit Java-ish… but of course I’ll keep the C# casing convention.

The underlying type used to represent an enum is an integer by default, but other types can be used, such as a long or an unsigned short. I will try to make the enums definitions as short a possible, so I’ll use generics and take advantage of the type inference system.

As you can see in the implementation, it is now possible to define a Gesture enum, that exposes 3 static properties of type Gesture. One of these properties, ROCK, is in fact an instance of RockGesture, which is a Gesture that overrides the behaviour of Beats method.

Strategy Pattern

All the Java sample from the post can now be ported to C# ! The next one was the Eurovision contest, where an abstract method was defined in the base enum, and overridden in each enum instance, in order to implement a strategy pattern. This is where I admit I couldn’t get the same behaviour, as for internal implementations reasons I needed my base class to not be abstract… So I had to define a default behaviour :

Just as for the Java enums, “we can reference enum constants between them, with the restriction that only constants defined before can be referenced”. The workaround here, as @cyriux wrote in his post, is to open the cycle. This builds allows us to build the graph on the right.

We can notice here that in order to embed data in an enum value, I have introduced an extra parameter “data” in the Enum method, which is responsible for the Enum values registration. Using this extra parameter, we can go back to the Eurovision sample and rewrite this way :

In this implementation, each enum value owns its notification policy, in the form of a types delegate, which is declared using a lambda expression.

Enum-non-optimized collections

Ok, I haven’t gone so far as implementing optimized collections that take advantage of the integer nature of enums ! So not all the arguments listed by @cyriux apply to my C# implementation… But I still get polymorphism, the correct Equals, GetHashCode, ToString, string or integer serialization, and singleton-ness for free, with very little code ! Feel free to experiment with it if you want, the whole project will be available on my GitHub very soon.

In a next post, I’m going to talk about some points of interest in my PolymorphicEnum implementation.