Eventually, you need to upgrade from enums to classes in
order to encapsulate both their state and behavior, if their behavior expands
beyond mere named constants. The best way to achieve this without breaking the
enum use pattern is through the use of static classes. When done properly,
this refactoring can be done with little or no changes required in existing
code that previously used the enum. Consider the following Role class that can
be used everywhere our existing enum was used in the previous examples:

In Visual Studio, when you type in "Role." you
will get the following Intellisense:

Thus, the behavior mirrors that of an enum, constraining the
options available. The friendly display value is easily displayed without the
need for attributes or reflection, using this code:

The issue with passing in values that are outside the range
of the enumeration disappears as well. The only way one could do such a thing
would be through the use of reflection to remove the sealed marker on Role and
create a subtype. Otherwise, whether an invalid value is cast or an
uninitialized value is passed into a method expecting a Role, an exception will
result (you may wish to do your own null check). These two tests both pass
now:

The new implementation of RoleCanDoSomething() is simply:

And of course, now that Role is an actual class, some of
these utility methods that were in EnumHelper or RoleHelper classes can be
rolled into the Role class itself, if appropriate.