Click here to Skip to main content
14,028,419 members
Click here to Skip to main content
Add your own
alternative version


42 bookmarked
Posted 9 Oct 2007

Enhancing C# Enums

, 11 Oct 2007
Rate this:
Please Sign up or sign in to vote.
How to make a class look like an enum with added functionality


An enum in C# is a value type that is used to represent a set of fixed distinct values so that it can be used later in program logic. A very straightforward example of a classic enum declaration is given below:

public enum Rating
    Awful = 1,
    Bad = 2,
    Medium = 3,
    Good = 4,
    Awesome = 5

The enum above describes a set of possible values that a variable of type Rating can assume. This way, we can use it in our code to implement any kind of logic in a type-safe way. For instance, if we have a Rating variable called userRating, we could use it like this:

if(userRating == Rating.Awesome)
    //Do something

If we try to cast an int that was not defined in the enum list, I would expect the runtime to throw an exception. However, the funny thing is that the line of code bellow will create a variable rating with the value 6.

Rating rating = (Rating)6; //does not throw an exception

The way I see it, it is not a good thing, since our enum could be used improperly and we would only be able to validate it in another class. Besides that, sometimes it's useful to add some functionality to enums. The problem is that they have some limitations. Since it's not a class, it cannot be extended and its defined values are limited to a small set of primitive types (byte, sbyte, short, ushort, int, uint, long, ulong). For instance, sometimes it is very convenient to get the list of enum values and display it in a combobox. Although there are some reflection techniques that let you define and retrieve descriptions for the enum items, you are always limited to a key and a value.


To overcome these limitations, we can use a regular class to represent an enum while keeping the same basic characteristics. Here's the code of the base class that we will use to implement the enhanced enums.

using System.Collections.ObjectModel;
public abstract class EnumBaseType<T> where T : EnumBaseType<T>
    protected static List<T> enumValues = new List<T>();

    public readonly int Key;
    public readonly string Value;

    public EnumBaseType(int key, string value)
        Key = key;
        Value = value;

    protected static ReadOnlyCollection<T> GetBaseValues()
        return enumValues.AsReadOnly();

    protected static T GetBaseByKey(int key)
        foreach (T t in enumValues)
            if(t.Key == key) return t;
        return null;
    public override string ToString()
    return Value;

Note that in this class we define a key and a value field. This corresponds to the classical enum implementation, but now we are not limited to a key and a value. If required, we can extend this class and add new fields to the structure. Here is the actual implementation of our enhanced Rating enum:

public class Rating : EnumBaseType<Rating>
    public static readonly Rating Awful = new Rating(1, "Awful");
    public static readonly Rating Bad = new Rating(2, "Bad");
    public static readonly Rating Medium = new Rating(3, "Medium");
    public static readonly Rating Good = new Rating(4, "Good");
    public static readonly Rating Awesome = new Rating(5, "Awesome");

    public Rating(int key, string value) : base(key, value)

public static ReadOnlyCollection<Rating> GetValues()
        return GetBaseValues();

    public static Rating GetByKey(int key)
        return GetBaseByKey(key);

Now it can be used as a regular enum in an if statement and can also iterate through the values defined in our class. Notice that, because they are static, we still need to explicitly implement the methods GetValues() and GetByKey() if we want to use them. Otherwise, the enumValues collection would be empty.

foreach (Rating rating in Rating.GetValues())
    Console.Out.WriteLine("Key:{0} Value:{1}", rating.Key, rating.Value);

    if (rating == Rating.Awesome)
        //Do something

Now let's pretend we are using our Rating enum to rate movies on a website and we want to associate a "Must See" field to the rating, so that Good and Awesome movies display the "Must See" icon besides it. To do that, we have to add a new field to our Rating class. So now the Rating implementation is going to look like this:

public class Rating : EnumBaseType<Rating>
    public static readonly Rating Awful = new Rating(1, "Awful", false);
    public static readonly Rating Bad = new Rating(2, "Bad", false);
    public static readonly Rating Medium = new Rating(3, "Medium", false);
    public static readonly Rating Good = new Rating(4, "Good", true);
    public static readonly Rating Awesome = new Rating(5, "Awesome", true);

    public readonly bool MustSee;

    public Rating(int key, string value, bool mustSee) : base(key, value)
        this.MustSee = mustSee;

    public static ReadOnlyCollection<Rating> GetValues()
        return GetBaseValues();

    public static Rating GetByKey(int key)
        return GetBaseByKey(key);

Although we added new information to the Rating class, the clients using this enhanced enum will not be affected by this change. In addition, they will have the new MustSee field available.

foreach (Rating rating in Rating.GetValues())
    if (rating.MustSee)
        Console.Out.WriteLine("This is a Must See movie!");


The only drawback of this approach is that the enhanced enum cannot be used in a switch statement, since its values are not constants. However, I still think it's worth using it when you need advanced functionality associated with your enums.


In this article, we saw how to use classes to simulate the behavior of enums while leveraging OOP techniques to enhance their capabilities. I hope, in the future, that the C# team includes some syntax sugar to allow the use of advanced enums without the need to write custom code and without the drawback concerning switch statements.


  • 9 October, 2007 -- Original version posted
  • 11 October, 2007 -- First update


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Cassio Mosqueira
Software Developer (Senior) Intelligent Coder
Canada Canada
I've been developing .NET enterprise applications since 2000.

I am originally from Rio de Janeiro and I am currently working at in Ontario.

I also have my own startup where we offer client intake forms.

You may also be interested in...

Comments and Discussions

QuestionNot working on some cases Pin
slelong15-Nov-14 23:44
memberslelong15-Nov-14 23:44 
AnswerRe: Not working on some cases Pin
tridy4-Mar-15 21:11
membertridy4-Mar-15 21:11 
GeneralYeah but ... Pin
thugthug31-Mar-10 9:23
memberthugthug31-Mar-10 9:23 
GeneralRe: Yeah but ... Pin
charles henington4-Feb-13 5:12
membercharles henington4-Feb-13 5:12 
GeneralExtend some more... Pin
dancerjohn16-Oct-07 3:08
memberdancerjohn16-Oct-07 3:08 
GeneralRe: Extend some more... Pin
Cassio Mosqueira16-Oct-07 4:20
memberCassio Mosqueira16-Oct-07 4:20 
GeneralSystem.Enum Pin
Rdunzl14-Oct-07 15:17
memberRdunzl14-Oct-07 15:17 
GeneralRe: System.Enum Pin
Cassio Mosqueira14-Oct-07 15:36
memberCassio Mosqueira14-Oct-07 15:36 
GeneralRe: System.Enum [modified] Pin
Rdunzl14-Oct-07 19:45
memberRdunzl14-Oct-07 19:45 
I have very little knowledge of Java (although I've read several books about refactoring and design patterns based on the Java language and I know that most of our Nxxxx goodies are borrowed from the Java domain).

I have missed enum extensibility a few times myself, but I have sort of accepted that enums are not extensible, and I have always been able to find a workaround in those rare cases. Of course what you do is ok to do if it's appropriate. I understand enums as simple value types and as such they don't really need any kind of extension.

You can iterate through System.Enum.GetNames(typeof(MyEnum)) or System.Enum.GetValues(typeof(MyEnum)) so I think that your example is an example where you should stick to just using enums and keep the benefit of communicating to other developers that they are dealing with simple value types.

I personally try to stick to the Design guidelines for developing class libraries[^] as much as possible. Of course it's a matter of taste whether to use those conventions or not, but it works fine for me. According to those guidelines your suggestion is an example of incorrect design (Enumeration Design[^]).

I would like to know what other extensibility you miss in the case of enumerations.

A completely other thing is that you are dealing with a kind of "borderline case" where you have to decide whether the matter you're expressing as a type could be regarded as either an enum or a class. The term "borderline case" is my own and covers decisions of whether to express a given matter as enum, struct or class, decisions about whether an attribute should be a method or a property and whether some functionality should be a method or a class (like Kent Beck's method object and the GoF command pattern ).

I find those borderline cases interesting (from a semiotically point of view), and I guess that you are confronted with more of those cases since you use both Java and C#.

Maybe you can use the new VS2008 extension method-functionality to achieve what you want by making a few extensions on System.Enum (works for dotnet 2.0 too as long as you use VS2008 as IDE). That could mean that you would be able to achieve the behavior you want and keep using the enum type as well Smile | :)

-- modified at 1:50 Monday 15th October, 2007
GeneralRe: System.Enum Pin
Cassio Mosqueira15-Oct-07 3:22
memberCassio Mosqueira15-Oct-07 3:22 
GeneralRe: System.Enum Pin
Rdunzl15-Oct-07 20:12
memberRdunzl15-Oct-07 20:12 
GeneralEnum statics Pin
Thomas Lykke Petersen11-Oct-07 19:31
memberThomas Lykke Petersen11-Oct-07 19:31 
GeneralGood idea, but ... Pin
Jakub Mller10-Oct-07 22:04
memberJakub Mller10-Oct-07 22:04 
GeneralGood Job Pin
merlin98110-Oct-07 3:49
professionalmerlin98110-Oct-07 3:49 
GeneralRe: Good Job Pin
Cassio Mosqueira10-Oct-07 4:55
memberCassio Mosqueira10-Oct-07 4:55 
Generalbase methods can be published Pin
_SAM_9-Oct-07 20:38
member_SAM_9-Oct-07 20:38 
GeneralRe: base methods can be published Pin
Cassio Mosqueira10-Oct-07 4:50
memberCassio Mosqueira10-Oct-07 4:50 
GeneralRe: base methods can be published Pin
_SAM_10-Oct-07 5:23
member_SAM_10-Oct-07 5:23 
GeneralRe: base methods can be published Pin
Cassio Mosqueira10-Oct-07 13:07
memberCassio Mosqueira10-Oct-07 13:07 
GeneralRe: base methods can be published Pin
dancerjohn16-Oct-07 3:20
memberdancerjohn16-Oct-07 3:20 
GeneralRe: base methods can be published Pin
Tim Schwallie16-Oct-07 16:23
memberTim Schwallie16-Oct-07 16:23 
QuestionHow about a Dictionary? Pin
PIEBALDconsult9-Oct-07 16:28
protectorPIEBALDconsult9-Oct-07 16:28 
AnswerRe: How about a Dictionary? Pin
Cassio Mosqueira9-Oct-07 18:10
memberCassio Mosqueira9-Oct-07 18:10 
GeneralRe: How about a Dictionary? Pin
PIEBALDconsult10-Oct-07 13:33
protectorPIEBALDconsult10-Oct-07 13:33 
GeneralAlternative for enum descriptions Pin
Scott Dorman9-Oct-07 14:23
professionalScott Dorman9-Oct-07 14:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web05 | 2.8.190419.4 | Last Updated 11 Oct 2007
Article Copyright 2007 by Cassio Mosqueira
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid