Enumeration, Alternative Way of Implementing and Using Enums in C# 🚀
In this post, I will try to explaing an alternative way to use instead of enums
. I already mentioned enums here. Enums
can be used in many places in our code base, especially in control flows. It’s enough for most cases but some situations can be problematic. Let’s say you are using the same enum in many control flows to decide the behaviour of the process. In this case, we scatter the business information throughout the program. At that point, we break down Open-Closed principle and make it hard to maintain because if we need a new enum value we should review all these and most likely change them explicitly.
For example, you have a system and there are service points to serve customer as a bank. In order to represent this, we can create an enum ServicePointType
as below,
We need to set a max amount for daily withdrawing limit. We can simply achieve that like this,
In the above code, we simulate an imaginary scenario that checks limit to withdraw money. Suppose there was a new ServicePointType
, we would have to add that value into WithdrawService
. We can achieve the same functionality without a switch statement and more object-oriented way. We can do this with Enumeration
class which c# provides us.
Let’s add a new Enumeration
class as a base,
We created Enumeration
class as a base class. It’s very similar to typical enums
. There are Id
and Name
fields that represent it. The constructor has a protected keyword because only subclasses can access and use it. We override the ToString
method to give the same behaviour as ServicePointType
because when we call Console.WriteLine(ServicePointType.Bank))
it will write Bank
text to output. The next method we implemented is GetAll<T>
to be able to use instead of Enum.GetValue<TEnum>()
. It uses System.Reflection
the same as enum
. The last method is CompareTo(object? other)
which comes from IComparable
interface to compare and sort their values. It’s same as Microsoft official implementation as you can find here.
Now, we can inherit Enumeration
class as below,
In the above, we created three instances of ServicePointTypeEnumeration
and they are shared across application. We give them related initial values in the place where they were created. We also extended with Limit
property to access from outside without needing a switch statement.
Note: As you recognize, one of the most important points is that we are using class
type(reference type) instead of enum
which is the value type. Therefore, we can enrich our objects as a benefit of object-oriented.
Let’s modify our WithdrawService
class to use it,
The difference from the previous implementation is that we don’t need GetLimit(ServicePointType servicePointType)
method anymore because we already have limit
value internally set. All we need is to access Limit
property.
This is not limited just Limit property. There can be any other object-related field you can extend or change behaviour. For example, enums
doesn’t support implicit conversion(you can find more detail here). We can implement it easily. All we need is to add one line of code to Enumeration
base class as below,
Now, code is valid as below,
As a result, enums are pretty enough in most cases but there could be some scenarios we can give solutions from a different perspective via Enumeration
. If you’re unsure about needing it, you should probably go with enum
.