Sortable and expandable enums

By Mirek on (tags: enums, categories: code)

Have you ever faced the problem that extending enum type by new values may cause unpredicted behavior of the application? I recently have. As the solution for this problem I figure out how to design enum values so they can be easily sortable and easily expandable in future, causing no side effect.

We have a simple enum type ConstructionSteps we use

public enum ConstructionSteps
{
    Undefined,
    Planning,
    Building,
    Approvement
}

 

The framework will automatically assign integer value to each of the enum value starting from 0 so it will look like this

public enum ConstructionSteps
{
    Undefined = 0,
    Planning = 1,
    Building = 2,
    Approvement = 3
}

 

Having integer representation of the enum gives us at least two advantages. First, when we use this enum type in Entity Framework model then it is mapped to integer type database column – the smallest possible representation of enum type. And the second having two variables of this enum type we can easily compare them like we do with integer numbers. Then having, for instance construction steps, as in our example, the integer representation additionally indicates the order of each step by its value.

Having that we are able to sort collection of enum values by its value.

List<ConstructionSteps> steps = ((ConstructionSteps[])Enum.GetValues(typeof(ConstructionSteps))).ToList();
var lastStep = steps.OrderByDescending(s => s).FirstOrDefault();

 

The problem I want to describe concerns extending enum type definition by new values. Since adding values at the end of the list is not a problem

public enum ConstructionSteps
{
    Undefined = 0,
    Planning = 1,
    Building = 2,
    Approvement = 3,
    Finalization = 4
}

but when we later on want to add an intermediate step which would have place between Planing and Building then we need to shift the numeric representations of all values after the new one

public enum ConstructionSteps
{
    Undefined = 0,
    Planning = 1,
    Preparation = 2,
    Building = 3,
    Approvement = 4,
    Finalization = 5
}

And here we have a problem with database update. Since Entity Framework will not detect it as a model change (because the database schema did not changed in fact) we will need to manually update each value representing our enum type so shifted integer values still represents the same enum vaues.

The solution for this problem is a little tricky. The clue is to define numeric representation for each single enum value in the  way that it will allow to put future intermediate values not affecting existing ones.

public enum ConstructionSteps
{
    Undefined = 0,
    Planning = 10,
    Building = 20,
    Approvement = 30
}

Between each two steps we can later on define 9 intermediate steps without affecting he database

public enum ConstructionSteps
{
    Undefined = 0,
    Project = 5,
    Planning = 10,
    Preparation = 15,
    Building = 20,
    Approvement = 30
}

The only sensitive part is to properly foresee how many intermediate values we will need to add in the future, but I didn’t yet found a case when 9 spaces is not enough.

Extending enum type in this way simply keeps the values comparable and sortable and does not require to update enum references in the database.

 

Have a nice day!