Make Your Enums More Object-Oriented

Ahmet Murat Gençay
3 min readJan 16, 2021

According to Wikipedia, an enumerated type is a data type consisting of a set of named values called elements, members, enumeral, or enumerators of the type.

When a new feature is required in the software we have developed, it may make sense to define an enum to concrete some concepts quickly.

Then we realize the following issues:

1) Wherever we want to work with Enum, we have to use switch-cases,
2) We have to check the correctness of the numeric value to converting to Enum,
3) High maintenance cost due to lack of OOP features,

And the structure that seems easy at first becomes a burden on us over time.

In this article, I would like to mention a few practical design patterns that can be used for enums in certain situations.

Reduce Multiple Branching

Each element in an enum represents a branching that we need to consider in our application.

The following code is a simple angle conversion application.
Conversion between Degrees, Radians and Gradients causes
n * n = n² = 9 branches. When we add a new angle type, this branching number will continue to increase as n².

The easiest way to reduce the number of branches is to create an implementation of each branch-specific.

In the following code, branching is reduced by defining a dictionary containing the relationship between angle types. Also when a new angle type is defined, only the relationship between angle types will change.

Usage Examples:

AngleTypeEnumeration.ConvertAngle(30, Degree, Radian);
AngleTypeEnumeration.ConvertAngle(0.5, Radian, Gradian);

Compound Enums

In some cases, we may need to use more than one enum to indicate the state of a particular object. Unfortunately, .net doesn’t have a built-in solution for compound enums.

To solve this kind of requirements with traditional approaches cause an increasing number of branches. It will also cause us to make many changes in the code when new needs arise.

The following code reduces branching by defining a nested dictionary that contains the LanguageCode enum and the MessageType enum. When a new language code or message type is defined, it will be enough to make changes only in that enum.

Usage Examples:

Greeting.ToLocalizedMessage(Tr);
Farewell.ToLocalizedMessage(Fr);

Hierarchical Enums

Enums frequently uses with the factory design pattern. Working with enums in single-level factory methods meets our needs most of the time. On the other hand, in some cases, creating an object can be more complicated.

Besides, you can use the builder design pattern for such situations.

In the code below, we designed a factory for creating a car. The main problem here is that we need the car brand and model to create the object.

As a solution to the problems above, we created some classes containing the brand and model structure hierarchically.

Usage Examples:

Brands.Opel.Corsa.Create();
Brands.Opel.Create(Astra);

Multiple behaviours in flag enumerations

Although we are not in the 90s, using flag enums and bitwise operations can fit our needs more quickly in some cases. We have to consider such approaches as I mentioned above because it can easily break the object-oriented rules in the code.

In the example below, we used the ValidationTypes flag enum to manage validation controls. This approach will cause an increase both in the number of bitwise operations in the code and the spaghetti codes.

As a solution to these problems, we defined a list that contains the behaviours of enum values.

Usage Examples:

EMail.Validate(“amuratgencay@gmail.com”);
PhoneNumber.Validate("555");

Summary

Enums will continue to be in our life for a long time. Especially in legacy applications, they will often challenge us by their frequent and incorrect usage.

On the other hand, we can make our work easier and reduce maintenance costs with a few object-oriented approaches.

Following are some of our most helpful tools in this process.

  1. Extension methods
  2. Enum classes
  3. Delegates
  4. Collections

References

  1. Enumerated type
  2. How to create a new method for an enumeration (C# Programming Guide)
  3. Use enumeration classes instead of enum types
  4. Func<T,TResult> Delegate
  5. Enumeration types (C# reference)
  6. Collection C#

--

--