Java like Enums in C#

Shabbir Bawaji
3 min readMar 1, 2022

Java has very powerful features for Enums because not only does it help you create a constraint list of values but also allows you to store more, meaningful and readable data as well as allows you to define its own functions. On the other hand, Enums in C# are not that flexible, the only data that can be stored within each enum value is just an integer and it cannot have any member functions as well.

To see the comparison let’s take an example of modeling Currencies using Java Enum.

public enum Currency {
USD('$', 1),
INR('₹', 0.01324F),
POUND('£', 1.3423F),
EURO('€', 1.1228F);
private final char symbol;
private final float USDconvertionRate;
Currency(char symbol, float USDconvertionRate) {
this.symbol = symbol;
this.USDconvertionRate = USDconvertionRate;
}
public float ConvertTo(Currency other, int amount) {
float toUSD = this.USDconvertionRate * amount;
return toUSD / other.USDconvertionRate;
}
public String ReadableAmount(float amount) {
return this.symbol + Float.toString(amount);
}
}

The above example would be a little hard to implement with such ease in C# for the following reasons

  1. USDconvertionRate is a floating-point datatype
  2. function that would need to be in a util static class
  3. symbol character would need another storage data structure.

Now that the problem is clearer, what would be the solution?

Before moving to the solution let’s take a minute to think about Enum in general. Enum is basically a special type of class providing some sugar-coated syntax. The values can only be initialized within its scope itself including its properties.

From the description of Enum above it must be obvious that the solution I am about to suggest is a class. So let’s look at how that code might look.

public class Currency {
private readonly char _symbol;
private readonly float _USDconvertionRate;
private Currency(char symbol, float USDconvertionRate){
_symbol = symbol;
_USDconvertionRate = USDconvertionRate;
}

public static readonly Currency USD = new Currency('$', 1);
public static readonly Currency INR = new Currency('₹', 0.01324F);
public static readonly Currency POUND = new Currency('£', 1.3423F);
public static readonly Currency EURO = new Currency('€', 1.1228F);
public float ConvertTo(Currency other, int amount) {
float toUSD = this._USDconvertionRate * amount;
return toUSD / other._USDconvertionRate;
}
public String ReadableAmount(float amount) {
return this._symbol + amount.toString();
}
}

The above solution makes us write more lines of code in terms of initializing each enum value but the rest of the code is the same. Initializing each of these values using static readonly” access modifier helps in having the same syntax of accessing these Enum values and yet not being able to change later on.

Java also provides util to get the list of Enum values. So how do we implement this in C#? There are two ways of doing it

  1. By manually defining the list within the class and specifying it as a getter.
public static List<Currency> Values = new List<Currency> {
USD, INR, POUND, EURO
}

But with this approach, once the value is initialized, you also need to add it to the above list as well. So how can we automate the values being added to the list?

2. By using reflections to identify which property types are of type currency and part of the enum

public static List<Currency> Values {
get {
return new List<FieldInfo>(USD.GetType()
.GetFields(BindingFlags.Public | BindingFlags.Static))
.Where(f => f.FieldType == typeof(Currency))
.Select(f => (Currency) f.GetValue(null))
.ToList();
}
}

And the list can still be accessed by Currency.Values

Of course, the above Enum values cannot be used in switch cases as the case values should be a constant, but if there is a huge if-else ladder then that is code smell as well.

--

--